jekyll-theme-zer0 1.27.0 → 1.29.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 +812 -13
- data/_data/backlog.yml +356 -2
- data/_data/consumers.yml +252 -0
- data/_data/features.yml +234 -5
- data/_data/i18n/fr.yml +103 -0
- data/_data/i18n/manifest.yml +1529 -0
- data/_data/ingredient_densities.yml +122 -0
- data/_data/navigation/docs.yml +2 -0
- data/_data/navigation/main.yml +22 -0
- data/_data/recipe_courses.yml +64 -0
- data/_data/series.yml +19 -0
- data/_data/theme-manifest.yml +387 -277
- data/_data/ui-text.yml +8 -0
- data/_includes/README.md +36 -3
- 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/background-customizer.html +2 -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/cookie-consent.html +4 -4
- data/_includes/components/data-card.html +95 -0
- data/_includes/components/halfmoon.html +5 -1
- data/_includes/components/info-section.html +8 -3
- data/_includes/components/language-toggle.html +168 -21
- data/_includes/components/page-feedback.html +65 -2
- data/_includes/components/page-views-init.html +55 -0
- data/_includes/components/page-views.html +33 -0
- data/_includes/components/recipe-card.html +67 -0
- data/_includes/components/recipe-duration.html +50 -0
- data/_includes/components/recipe-grams.html +58 -0
- data/_includes/components/recipe-index.html +96 -0
- data/_includes/components/recipe-ingredients.html +90 -0
- data/_includes/components/recipe-meta.html +96 -0
- data/_includes/components/recipe-nutrition.html +57 -0
- data/_includes/components/recipe-qty.html +73 -0
- data/_includes/components/recipe-ratio.html +151 -0
- data/_includes/components/recipe-scaler.html +73 -0
- data/_includes/components/recipe-steps.html +86 -0
- data/_includes/components/recipe-temp.html +45 -0
- data/_includes/components/search-modal.html +2 -2
- data/_includes/components/shortcuts-modal.html +3 -0
- data/_includes/components/theme-controls-bar.html +10 -2
- data/_includes/components/theme-customizer.html +8 -2
- data/_includes/components/theme-info.html +8 -1
- data/_includes/content/jsonld-software.html +22 -3
- 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 +18 -16
- data/_includes/core/head.html +21 -0
- data/_includes/core/header.html +7 -4
- 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/local-graph.html +28 -2
- data/_includes/navigation/nav-tree.html +3 -3
- data/_includes/navigation/section-sidebar.html +93 -11
- data/_includes/navigation/sidebar-config.html +21 -0
- data/_includes/navigation/sidebar-left.html +2 -1
- data/_includes/navigation/sidebar-nav.html +4 -0
- data/_includes/navigation/sidebar-pagetree.html +150 -0
- data/_includes/navigation/sidebar-right.html +2 -1
- data/_includes/navigation/unified-drawer.html +8 -2
- data/_includes/obsidian/full-graph.html +165 -136
- data/_includes/setup/wizard.html +173 -86
- data/_includes/stats/stats-metrics.html +2 -2
- data/_layouts/404.html +260 -0
- data/_layouts/README.md +4 -0
- data/_layouts/admin.html +2 -2
- data/_layouts/article.html +5 -0
- 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/cookbook.html +88 -0
- data/_layouts/default.html +4 -4
- data/_layouts/home.html +5 -2
- data/_layouts/landing.html +9 -0
- data/_layouts/news.html +155 -31
- data/_layouts/recipe.html +274 -0
- data/_layouts/root.html +38 -5
- data/_layouts/section.html +96 -25
- data/_sass/components/_book.scss +423 -0
- data/_sass/components/_callout.scss +1 -1
- data/_sass/components/_footer.scss +37 -1
- data/_sass/components/_page-views.scss +36 -0
- data/_sass/components/_recipe.scss +506 -0
- data/_sass/components/_setup-wizard.scss +235 -0
- data/_sass/components/_ui-enhancements.scss +6 -6
- data/_sass/core/_navbar.scss +263 -15
- data/_sass/core/_obsidian.scss +286 -6
- data/_sass/layouts/_landing.scss +2 -2
- data/_sass/theme/_backgrounds.scss +21 -8
- data/_sass/tokens/_color.scss +6 -0
- data/_sass/tokens/_index.scss +2 -0
- data/_sass/tokens/_radius.scss +21 -0
- data/_sass/tokens/_typography.scss +4 -0
- data/_sass/utilities/_focus.scss +14 -0
- data/assets/css/main.scss +4 -0
- data/assets/js/auto-hide-nav.js +5 -1
- data/assets/js/halfmoon.js +26 -0
- data/assets/js/modules/navigation/navbar.js +55 -0
- data/assets/js/obsidian-graph.js +702 -264
- data/assets/js/obsidian-local-graph.js +161 -54
- data/assets/js/page-views.js +372 -0
- data/assets/js/recipe-scaler.js +501 -0
- data/assets/js/search-modal.js +14 -1
- data/assets/js/setup-wizard.js +322 -20
- data/scripts/README.md +29 -0
- data/scripts/bin/audit-consumer +39 -7
- data/scripts/bin/giscus-discussions +213 -14
- data/scripts/bin/manifest +66 -16
- data/scripts/bin/validate +5 -1
- data/scripts/ci/agent_review_result.py +164 -0
- data/scripts/ci/test_agent_review_result.py +172 -0
- data/scripts/design-system-check.rb +170 -0
- data/scripts/install/README.md +47 -6
- data/scripts/install/ai/client.sh +302 -93
- data/scripts/install/ai/prompts/spec.schema.json +1 -1
- 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/audit.sh +42 -2
- data/scripts/lint-liquid-raw.rb +137 -0
- data/scripts/propagate.rb +277 -0
- data/scripts/test/lib/run_tests.sh +2 -1
- data/scripts/test/lib/test_agent_review_result.sh +27 -0
- data/scripts/translate.rb +161 -15
- metadata +56 -2
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,805 @@ 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.29.0](https://github.com/bamr87/zer0-mistakes/compare/v1.28.0...v1.29.0) (2026-09-01)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **analytics:** track and display per-page view counts ([#413](https://github.com/bamr87/zer0-mistakes/issues/413)) ([e488c4c](https://github.com/bamr87/zer0-mistakes/commit/e488c4c3101da78e98eecbf8299ce7c8705ed281))
|
|
21
|
+
* **design:** fill Fab, PostCard, Skeleton + motion/layers gaps in the design-system mirror ([#391](https://github.com/bamr87/zer0-mistakes/issues/391)) ([3b49741](https://github.com/bamr87/zer0-mistakes/commit/3b497417564b4c5e3d71eaa113cb136d2cdaf15c))
|
|
22
|
+
* **includes:** icon-only language trigger and a compact, positive menu ([#431](https://github.com/bamr87/zer0-mistakes/issues/431)) ([353bfa5](https://github.com/bamr87/zer0-mistakes/commit/353bfa5f3a8dd949ca6e513213a155d648218642)), closes [#406](https://github.com/bamr87/zer0-mistakes/issues/406)
|
|
23
|
+
* **includes:** live preview, vertical stepper and draft persistence in the setup wizard ([#432](https://github.com/bamr87/zer0-mistakes/issues/432)) ([73bdc55](https://github.com/bamr87/zer0-mistakes/commit/73bdc5547350c448e1617ec6cf5b9f49b10d65fb)), closes [#408](https://github.com/bamr87/zer0-mistakes/issues/408)
|
|
24
|
+
* **layouts:** add cookbook collection with recipe scaling and unit conversion ([#414](https://github.com/bamr87/zer0-mistakes/issues/414)) ([bb8eefa](https://github.com/bamr87/zer0-mistakes/commit/bb8eefa2beea0104fec28d173a1e57f369acada8))
|
|
25
|
+
* **pages:** publish the design system and page canvas on the live site ([#392](https://github.com/bamr87/zer0-mistakes/issues/392)) ([6cf73cd](https://github.com/bamr87/zer0-mistakes/commit/6cf73cdf2cca9ec02394b6ae1ba7e39c19969134))
|
|
26
|
+
* **sass:** align design tokens with the Claude Design system ([#389](https://github.com/bamr87/zer0-mistakes/issues/389)) ([7fc2fe0](https://github.com/bamr87/zer0-mistakes/commit/7fc2fe02683d652c0326536158bd48b3690df51f))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Bug Fixes
|
|
30
|
+
|
|
31
|
+
* **a11y:** dialog titles use a bare <h5>, skipping heading levels ([#387](https://github.com/bamr87/zer0-mistakes/issues/387)) ([98fd6f9](https://github.com/bamr87/zer0-mistakes/commit/98fd6f9e63dfb75c58efc3b15a642fb3e4c4095b))
|
|
32
|
+
* **ci:** fail the content review when it did not actually run ([#424](https://github.com/bamr87/zer0-mistakes/issues/424)) ([f048cb2](https://github.com/bamr87/zer0-mistakes/commit/f048cb22e565b3122d6682c026e13521b6fe52d9)), closes [#418](https://github.com/bamr87/zer0-mistakes/issues/418)
|
|
33
|
+
* **ci:** fail the Pages build on Liquid errors, unmangle two live pages ([#439](https://github.com/bamr87/zer0-mistakes/issues/439)) ([afd2ec8](https://github.com/bamr87/zer0-mistakes/commit/afd2ec83879a793d77dfac21b41d74d5204126c4))
|
|
34
|
+
* **ci:** make the pixel gate see the data files that move pixels ([#425](https://github.com/bamr87/zer0-mistakes/issues/425)) ([02ea639](https://github.com/bamr87/zer0-mistakes/commit/02ea639b3152900682ca298bd172925133d10dea)), closes [#417](https://github.com/bamr87/zer0-mistakes/issues/417)
|
|
35
|
+
* **ci:** stop discarding good translations when one page fails ([#388](https://github.com/bamr87/zer0-mistakes/issues/388)) ([19cea46](https://github.com/bamr87/zer0-mistakes/commit/19cea462a7822d6db536fc9c23218abd4a13d830))
|
|
36
|
+
* **ci:** wait past the cold bundle install for Jekyll in the snapshot gate ([#426](https://github.com/bamr87/zer0-mistakes/issues/426)) ([de1d1ca](https://github.com/bamr87/zer0-mistakes/commit/de1d1ca426ce7a25d5a8548c4a696c0002877200))
|
|
37
|
+
* **cookie-consent:** text-dark on bg-body made privacy rights invisible in dark mode ([#386](https://github.com/bamr87/zer0-mistakes/issues/386)) ([9bde7df](https://github.com/bamr87/zer0-mistakes/commit/9bde7dfa13f426908e00e53f8e4013a049fd928d))
|
|
38
|
+
* **giscus:** comments were broken sitewide — add an end-to-end health check and correct the docs ([#378](https://github.com/bamr87/zer0-mistakes/issues/378)) ([45e222c](https://github.com/bamr87/zer0-mistakes/commit/45e222c3c2c5b7c507af4df2f5f0b48bc783801e))
|
|
39
|
+
* **includes:** footer Info/Cookie Preferences are buttons, not anchors ([#427](https://github.com/bamr87/zer0-mistakes/issues/427)) ([f9041b9](https://github.com/bamr87/zer0-mistakes/commit/f9041b98b8a267be59f560724821fd941090f52d)), closes [#320](https://github.com/bamr87/zer0-mistakes/issues/320)
|
|
40
|
+
* **layouts:** match section topic filters on whole tags, not substrings ([#420](https://github.com/bamr87/zer0-mistakes/issues/420)) ([338ad1d](https://github.com/bamr87/zer0-mistakes/commit/338ad1ddfb71c8d1dd9c48b36fb4634daf93f2de))
|
|
41
|
+
* **layouts:** move keyboard focus to the skip-link target (tabindex="-1") ([#395](https://github.com/bamr87/zer0-mistakes/issues/395)) ([f5db650](https://github.com/bamr87/zer0-mistakes/commit/f5db65048e48ca71eedebc04d02d051e0b3152a6)), closes [#278](https://github.com/bamr87/zer0-mistakes/issues/278)
|
|
42
|
+
* **layouts:** stop emitting dead sub-topic anchors in section sidebars ([#402](https://github.com/bamr87/zer0-mistakes/issues/402)) ([f50e790](https://github.com/bamr87/zer0-mistakes/commit/f50e790c4bfd56fefa4a74d7876de90c9776c689))
|
|
43
|
+
* **layouts:** upgrade the no-js class to "js" so the hook works ([#428](https://github.com/bamr87/zer0-mistakes/issues/428)) ([a2d31f5](https://github.com/bamr87/zer0-mistakes/commit/a2d31f5533a4fb4793042e32326c1a78c9954268)), closes [#319](https://github.com/bamr87/zer0-mistakes/issues/319)
|
|
44
|
+
* **navigation:** fit all nav items, full-bleed bar, language into Settings ([#423](https://github.com/bamr87/zer0-mistakes/issues/423)) ([689006e](https://github.com/bamr87/zer0-mistakes/commit/689006e7654e900a4509c30539fcf12bd7f397c6))
|
|
45
|
+
* **scripts:** correct consumer auditor, plugin contract, and JSON-LD scope ([#400](https://github.com/bamr87/zer0-mistakes/issues/400)) ([b466cad](https://github.com/bamr87/zer0-mistakes/commit/b466cad526501e7e7a0eef5f24a12c5bbd181dc7))
|
|
46
|
+
* **scripts:** recover from a rejected Anthropic credential, and link the cookbook ([#419](https://github.com/bamr87/zer0-mistakes/issues/419)) ([fac6bee](https://github.com/bamr87/zer0-mistakes/commit/fac6beeb7af7dcae96f727bf0cf581b080e95f15))
|
|
47
|
+
* **ui-audit:** serve without --detach so the sweep can capture, and fail loudly when it cannot ([#434](https://github.com/bamr87/zer0-mistakes/issues/434)) ([fac6415](https://github.com/bamr87/zer0-mistakes/commit/fac641574c951b2887d94f8b39561fb8b6f8fe8c)), closes [#321](https://github.com/bamr87/zer0-mistakes/issues/321)
|
|
48
|
+
|
|
49
|
+
## [Unreleased]
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- **Setup wizard: live preview, vertical stepper, draft persistence (T-040, #408)** —
|
|
54
|
+
the `_config.yml` preview is now a **persistent sticky panel** shown at every
|
|
55
|
+
step rather than an element inside step 5, regenerated on every keystroke,
|
|
56
|
+
with Copy and Download always enabled. The nav-pills tab row is replaced by a
|
|
57
|
+
left **vertical stepper** with done/active/upcoming state: a step is locked
|
|
58
|
+
until every earlier step validates, and Back is always allowed. The form is
|
|
59
|
+
mirrored to `localStorage` under `zer0-setup-draft` (debounced 300ms),
|
|
60
|
+
restored on load with a "Draft saved" chip, and cleared once the file is
|
|
61
|
+
downloaded. Email and URL fields are validated **on blur** with `is-invalid`
|
|
62
|
+
and an explanatory message, cleared as soon as you retype; the Review step
|
|
63
|
+
lists any unfilled recommended fields as warnings. Every step pane shares one
|
|
64
|
+
CSS grid cell, so the container is always as tall as the tallest step, and the
|
|
65
|
+
nav row is pinned to the bottom — **Back/Next no longer move vertically**
|
|
66
|
+
between steps. New
|
|
67
|
+
`_sass/components/_setup-wizard.scss`, and the wizard gains its first
|
|
68
|
+
automated coverage in `test/visual/features/setup-wizard.spec.js`.
|
|
69
|
+
|
|
70
|
+
Holding the container's height turned out to be only half of "Back/Next no
|
|
71
|
+
longer move": the nav row's own height still varied. Step 1's row was a block
|
|
72
|
+
box, so its button sat on a baseline and rode ~2px high, and in the real
|
|
73
|
+
~270px middle column `Review & Download` wrapped to a second line, pushing
|
|
74
|
+
that button's top up a further 16px. The row is now always a flex box and its
|
|
75
|
+
buttons never wrap. Draft persistence gained a matching fix: the 300ms
|
|
76
|
+
debounce meant the last edit before a reload was still only a queued timer and
|
|
77
|
+
was lost, so a pending write is now flushed on `pagehide` and on a hidden
|
|
78
|
+
`visibilitychange`. Before/after measurements are in
|
|
79
|
+
`test/visual/evidence/setup-wizard-nav-alignment/`.
|
|
80
|
+
|
|
81
|
+
- **Language switcher: icon-only trigger and a compact, positive menu (T-038, #406)** —
|
|
82
|
+
the navbar trigger drops its `EN` text span and the Bootstrap caret for a
|
|
83
|
+
38px square icon button, with `title` and `aria-label` carrying the language
|
|
84
|
+
name. In the menu (both the navbar dropdown and the Settings panel variant),
|
|
85
|
+
the current language is now marked with a tint and a check icon instead of
|
|
86
|
+
Bootstrap's `.active` primary fill, which read as a selected nav item rather
|
|
87
|
+
than "you are here". **Untranslated languages are no longer disabled rows** —
|
|
88
|
+
they link to the source page and still record the `zer0-lang` preference, so
|
|
89
|
+
the menu has no dead ends. Machine-generated translations carry a small
|
|
90
|
+
`auto` chip, and the per-row "(Not yet translated)" text — the main driver of
|
|
91
|
+
menu width — collapses into one footnote under a divider, referenced from
|
|
92
|
+
each marked row via `aria-describedby`. The dropdown menu is capped at 220px.
|
|
93
|
+
New `ui` keys `lang_machine_translated`, `lang_machine_translated_title` and
|
|
94
|
+
`lang_untranslated_note` in `_data/ui-text.yml`; each use carries a literal
|
|
95
|
+
fallback, because `core/i18n.html` replaces the `ui` map wholesale on a
|
|
96
|
+
translated page and `_data/i18n/<lang>.yml` will not have them until
|
|
97
|
+
`scripts/translate.rb` next runs.
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
|
|
101
|
+
- **Cookbook & recipes collection (ZER0-084)** — a `recipes` collection that
|
|
102
|
+
renders structured front matter as a working recipe page: `layout: recipe`
|
|
103
|
+
builds a fact bar (prep/cook/rest/total, yield, difficulty, cuisine, oven),
|
|
104
|
+
a grouped ingredient checklist, a numbered method with per-step timings and
|
|
105
|
+
temperatures, a baker's-percentage ratio table computed at build time, a
|
|
106
|
+
per-serving nutrition panel, and one `schema.org/Recipe` JSON-LD block.
|
|
107
|
+
`assets/js/recipe-scaler.js` adds serving scaling and live US↔metric
|
|
108
|
+
conversion — including volume↔weight via `_data/ingredient_densities.yml`
|
|
109
|
+
— as progressive enhancement, so every amount is still rendered exactly as
|
|
110
|
+
authored with JavaScript disabled. `layout: cookbook` indexes recipes into
|
|
111
|
+
course sections from `_data/recipe_courses.yml`. Twelve new
|
|
112
|
+
`components/recipe-*.html` includes, `_sass/components/_recipe.scss` (with
|
|
113
|
+
print styles), a demo cookbook at `/recipes/`, and docs at
|
|
114
|
+
[Cookbook collection](pages/_docs/features/cookbook-collection.md). Regression
|
|
115
|
+
coverage: `test/visual/features/recipes.spec.js` (smoke tier) and "Cookbook
|
|
116
|
+
Recipe Collection" in `test/test_core.sh` (evidence:
|
|
117
|
+
[`test/visual/evidence/recipes-collection/`](test/visual/evidence/recipes-collection/README.md)
|
|
118
|
+
— 0px page overflow across 320–1440px; 1 cup butter → 227 g, 500 g flour →
|
|
119
|
+
4 cups; ratio percentages identical at 1× and 3×).
|
|
120
|
+
|
|
121
|
+
- **Page-view counter (ZER0-083)** — the theme now tracks a view for the page
|
|
122
|
+
being read and displays the count in the article meta row, next to the
|
|
123
|
+
reading time (`👁 12 views`). Two providers, configured under `page_views:`
|
|
124
|
+
in `_config.yml`: `local` (the default — counts live in the visitor's
|
|
125
|
+
`localStorage`, so it works on GitHub Pages with no server, no network, and
|
|
126
|
+
no third party) and `remote` (counts come from an HTTP counter endpoint you
|
|
127
|
+
control, with `{path}` substitution, a configurable method, and a dotted
|
|
128
|
+
`count_key` for the response shape). Privacy gates mirror the `posthog:`
|
|
129
|
+
block — Do Not Track, Global Privacy Control, and an optional
|
|
130
|
+
`require_consent` tie-in to the cookie-consent "analytics" category — and
|
|
131
|
+
they suppress *recording* only, never the display of a count that is already
|
|
132
|
+
known; a view blocked pending consent is recorded when consent arrives.
|
|
133
|
+
`dedupe: session` counts one view per page per browser session so reloads do
|
|
134
|
+
not inflate it. The badge include (`components/page-views.html`) ships hidden
|
|
135
|
+
and is revealed only once a count exists, carrying its own leading separator
|
|
136
|
+
so a page with no data leaves no dangling bullet. New:
|
|
137
|
+
`_includes/components/page-views.html`,
|
|
138
|
+
`_includes/components/page-views-init.html`, `assets/js/page-views.js`,
|
|
139
|
+
`_sass/components/_page-views.scss`. Regression spec:
|
|
140
|
+
`test/visual/features/page-views.spec.js`. Docs:
|
|
141
|
+
[`docs/features/page-views.md`](docs/features/page-views.md)
|
|
142
|
+
(evidence: [`test/visual/evidence/page-views/`](test/visual/evidence/page-views/README.md)).
|
|
143
|
+
|
|
144
|
+
- **Search shortcut affordances (ZER0-032)** — the navbar search button now
|
|
145
|
+
advertises its keyboard shortcuts, matching the design-system navbar
|
|
146
|
+
pattern: a quiet `/` kbd chip (xl-up), a hover title ("Search — press / or
|
|
147
|
+
Ctrl+K", shown as `⌘K` on macOS), and `aria-keyshortcuts`; the sidebar (`b`)
|
|
148
|
+
and table-of-contents (`t`) hide toggles gained shortcut hover hints, and
|
|
149
|
+
the keyboard-shortcuts modal now lists `⌘/Ctrl+K`
|
|
150
|
+
(evidence: [`test/visual/evidence/search-shortcut-hint/`](test/visual/evidence/search-shortcut-hint/README.md)).
|
|
151
|
+
|
|
152
|
+
- **Live design-system pages (ZER0-082)** — the design system is now
|
|
153
|
+
part of the site itself: `_design-system/` is force-included in the Jekyll
|
|
154
|
+
build so `styles.css`, every token file, specimen cards, and component
|
|
155
|
+
sources get real URLs under `/_design-system/`; a new `/design/` hub page
|
|
156
|
+
renders the foundation specimens in live iframes (colors, skins, type,
|
|
157
|
+
spacing, radii, motion, layers, iconography), catalogs the component twins,
|
|
158
|
+
and links the Claude Design page canvas (all 24 layouts as a browsable
|
|
159
|
+
presentation). Navbar: About → Design System. Regression spec:
|
|
160
|
+
`test/visual/features/design-hub.spec.js`.
|
|
161
|
+
|
|
162
|
+
- **Claude Design system round-trip (ZER0-081)** — the design-token layer is now
|
|
163
|
+
aligned with the zer0-mistakes Claude Design project
|
|
164
|
+
(`claude.ai/design/p/e75121c0-9210-42d1-ade3-2c8af9111cbe`): new
|
|
165
|
+
`--zer0-radius-*`, `--zer0-logo-*`, and `--zer0-text-display-*` tokens in
|
|
166
|
+
`_sass/tokens/`; the design project vendored as a git mirror under
|
|
167
|
+
`_design-system/` (plain-CSS tokens, React component specs, guideline cards,
|
|
168
|
+
website UI kit — sync contract in `_design-system/SYNC.md`); and
|
|
169
|
+
`scripts/design-system-check.rb` wired into the core test suite so the theme
|
|
170
|
+
and the mirror cannot drift silently. Callouts, landing feature cards, mobile
|
|
171
|
+
nav, tables, and focus rings now consume the radius tokens (value-preserving —
|
|
172
|
+
rendered output unchanged, pinned by a new runtime token assertion in
|
|
173
|
+
`test/visual/core/styling.spec.js`).
|
|
174
|
+
- **Design-system component twins (PR #391)** — `Fab`/`FabStack`, `PostCard`,
|
|
175
|
+
and `Skeleton` join Button/Badge/Card/FeatureCard/Callout/Input in
|
|
176
|
+
`_design-system/components/`, plus new Motion and Layers foundation cards;
|
|
177
|
+
all pushed live to the Claude Design project. The feature registry is
|
|
178
|
+
re-synced (`features/features.yml` ↔ `_data/features.yml` — #389's ZER0-081
|
|
179
|
+
entry had landed in the `_data` mirror only, which the registry validator
|
|
180
|
+
rejects) and `docs/ui/components.md` gains a theme-source →
|
|
181
|
+
design-system-twin map.
|
|
182
|
+
|
|
183
|
+
### Changed
|
|
184
|
+
|
|
185
|
+
- **Language selector moved from the navbar into Settings → Appearance** — the
|
|
186
|
+
header utility cluster is now Search + Settings only, returning ~70px to the
|
|
187
|
+
menubar. `components/language-toggle.html` grew a `variant` parameter: the new
|
|
188
|
+
`panel` variant (shipped) renders a self-contained **Language** section — an
|
|
189
|
+
always-visible list of languages with the active one checked and
|
|
190
|
+
untranslated targets disabled — as the first block of the Settings
|
|
191
|
+
Appearance tab, next to Color Mode and Theme Skin. The original header
|
|
192
|
+
dropdown remains available as `variant="navbar"` for consumers that prefer
|
|
193
|
+
it. Same data, same `localStorage("zer0-lang")` preference, same
|
|
194
|
+
never-a-dead-link contract; `test/visual/features/language-toggle.spec.js`
|
|
195
|
+
was updated to exercise it through the Settings panel.
|
|
196
|
+
|
|
197
|
+
### Fixed
|
|
198
|
+
|
|
199
|
+
- **Footer "Info" and "Cookie Preferences" are buttons, not links (#320)** —
|
|
200
|
+
both controls open in-page UI (the `#info-section` offcanvas and the
|
|
201
|
+
`#cookieSettingsModal` modal) but shipped as `<a href="#" data-bs-toggle>`, so
|
|
202
|
+
assistive tech announced them as links — WCAG 4.1.2 Name, Role, Value — and
|
|
203
|
+
whenever Bootstrap's toggle did not fire the browser followed `href="#"` and
|
|
204
|
+
jumped the page to the top. All three occurrences are now
|
|
205
|
+
`<button type="button">`: the Info trigger is emitted **twice** by
|
|
206
|
+
`_includes/core/footer.html`, once in each branch of the powered-by loop, and
|
|
207
|
+
a site with no `powered_by` credits configured renders the branch a
|
|
208
|
+
single-site fix would have missed. `.powered-by-link` is now element-agnostic
|
|
209
|
+
(it already styled `<a>`, `<span>` and now `<button>`) and carries the
|
|
210
|
+
`<button>` reset Bootstrap Reboot does not supply — `appearance`,
|
|
211
|
+
`background`, `border`, `colour` — with the new `.footer-inline-button` doing
|
|
212
|
+
the same for a button in running text, so the swap is visually inert. The
|
|
213
|
+
back-to-top control keeps its `<a href="#">`: scrolling to the top is its
|
|
214
|
+
actual behaviour, not a side effect. Regression coverage: "Accessibility —
|
|
215
|
+
footer in-page toggles are buttons" in
|
|
216
|
+
`test/visual/core/accessibility.spec.js`, which asserts the element identity
|
|
217
|
+
directly — axe-core has no rule that fires on an anchor used as a button, so
|
|
218
|
+
an axe-based assertion passes on the broken markup too. "powered-by credits
|
|
219
|
+
are real links" in `test/visual/core/layout-chrome.spec.js` already banned
|
|
220
|
+
`href="#"` but sampled only the first five links, and `site.powered_by` pushed
|
|
221
|
+
the offending Info anchor past index 4; it now checks every credit link.
|
|
222
|
+
(evidence:
|
|
223
|
+
[`test/visual/evidence/footer-button-semantics/`](test/visual/evidence/footer-button-semantics/README.md)
|
|
224
|
+
— shipped vs. reset-stripped at 1280px, footer overflow 0px at 375/768/1280)
|
|
225
|
+
|
|
226
|
+
- **`<html class="no-js">` is upgraded to `js` again (#319)** — `_layouts/root.html`
|
|
227
|
+
shipped the standard progressive-enhancement hook but nothing ever swapped
|
|
228
|
+
it: the string `no-js` occurred in exactly one file in the repository, and in
|
|
229
|
+
no SCSS, JS, test or doc. Every page on every downstream site permanently
|
|
230
|
+
carried `no-js` with JavaScript fully enabled, so a consumer writing
|
|
231
|
+
`html.no-js .foo {…}` / `html.js .foo {…}` got the no-JS branch for everyone
|
|
232
|
+
— the class advertised a capability the theme did not deliver. An inline
|
|
233
|
+
script is now the **first child of `<head>`**, above
|
|
234
|
+
`{% include core/head.html %}` (which opens with Google Tag Manager, so
|
|
235
|
+
"first in that include" is not "first in `<head>`") and deliberately neither
|
|
236
|
+
`defer` nor `async`, since it has to run before the first stylesheet is
|
|
237
|
+
fetched or `html.js` rules would flash. The served HTML still carries
|
|
238
|
+
`class="no-js"`, so the JS-disabled branch stays correct and the change is
|
|
239
|
+
purely additive for consumers already styling against the served markup.
|
|
240
|
+
Regression coverage: `test/visual/core/progressive-enhancement.spec.js`
|
|
241
|
+
(smoke tier) pins both directions of the contract — `js` with scripts on,
|
|
242
|
+
`no-js` with them off — plus the delivery mechanism, because a fix that
|
|
243
|
+
simply deleted `class="no-js"` would satisfy a naive one-sided assertion
|
|
244
|
+
while removing the hook entirely.
|
|
245
|
+
|
|
246
|
+
- **Pages build: Liquid errors no longer ship mangled pages silently.** The
|
|
247
|
+
`github-pages` gem renders every non-excluded Markdown file through Liquid, so
|
|
248
|
+
prose that merely *looks* like a template is executed as one. Jekyll 3 reports
|
|
249
|
+
that as a `Liquid Warning`, drops the expression, and still exits 0 — so the
|
|
250
|
+
Pages workflow stayed green while publishing damaged pages. Two were live:
|
|
251
|
+
`/CHANGELOG/` rendered "Added `,,` and to the template renderer" because
|
|
252
|
+
`{% raw %}{{DEFAULT_BRANCH}}{% endraw %}` and its siblings were evaluated to
|
|
253
|
+
nothing, and `/_design-system/components/feedback/Skeleton.prompt/` rendered
|
|
254
|
+
`<div style=>` because the JSX `style={% raw %}{{ … }}{% endraw %}` was a
|
|
255
|
+
Liquid syntax error. A third defect was invisible: a literal
|
|
256
|
+
`{% raw %}{% raw %}{% endraw %}` written as prose in a changelog entry opened a
|
|
257
|
+
real block that swallowed the next 945 lines of the published page. All the
|
|
258
|
+
affected spans are now escaped, `pages.yml` fails the build on
|
|
259
|
+
`Liquid Warning`/`Liquid Exception` for both the theme and the example site,
|
|
260
|
+
and `scripts/lint-liquid-raw.rb` (wired into the `quality` suite) catches the
|
|
261
|
+
silent half — an unbalanced raw block never raises a warning to gate on.
|
|
262
|
+
|
|
263
|
+
- **Navbar: every top-level item now fits, at every desktop width** — the bar
|
|
264
|
+
was pinned inside a centred `.container-xl` (max 1140–1320px), so the menubar
|
|
265
|
+
track never got more than ~740px against the ~815px the theme's seven items
|
|
266
|
+
need. Every label rendered truncated — `Quick …`, `N…`, `Note…`, `A…` — while
|
|
267
|
+
the page had 100+px of unused margin on either side, and below ~1050px the
|
|
268
|
+
whole menu collapsed to bare icons. Four changes give the labels their room:
|
|
269
|
+
the bar is now `.container-fluid` and spans the full screen width (opt back
|
|
270
|
+
into a cap with `--zer0-navbar-max-width`); the brand cluster is capped at
|
|
271
|
+
`30cqi` of the bar so a long title cannot starve the menubar; label density
|
|
272
|
+
degrades in three measured tiers instead of two (icon + label ≥ 51rem →
|
|
273
|
+
label-only 41–50.99rem → icon-only < 41rem), each boundary set to the width
|
|
274
|
+
the tier below it actually needs; and the home-link icons wait for 86rem,
|
|
275
|
+
where they no longer cost the menubar more than it can spare. Measured on the
|
|
276
|
+
demo site: **0 truncated labels from 992px to 2560px** (was: all 7 truncated
|
|
277
|
+
at 1440px, all 7 icon-only at 992px). Regression coverage: "no nav label is
|
|
278
|
+
CSS-truncated at any desktop width" / "the bar spans the full viewport width"
|
|
279
|
+
/ "the brand title stays legible next to the menubar" in
|
|
280
|
+
`test/visual/features/navbar.spec.js` — the pre-existing label test only
|
|
281
|
+
checked for a literal `...` in `textContent`, which CSS `text-overflow` never
|
|
282
|
+
writes, so it passed throughout (evidence:
|
|
283
|
+
[`test/visual/evidence/navbar-fit/`](test/visual/evidence/navbar-fit/README.md)
|
|
284
|
+
— up to 7 truncated labels and 300px of dead bar margin → 0 across 8 widths).
|
|
285
|
+
|
|
286
|
+
- **Settings no longer opens behind the mobile nav menu** — on phones, tapping
|
|
287
|
+
**Settings** inside the open navigation menu appeared to do nothing: the
|
|
288
|
+
Settings offcanvas and the nav menu are both `offcanvas-end` panels at
|
|
289
|
+
Bootstrap's `$zindex-offcanvas`, and `_navbar.scss` lifts the fixed header
|
|
290
|
+
(which contains the nav menu) to 1046 while that menu is open — so Settings
|
|
291
|
+
painted underneath it, fully hidden. `navbar.js` now intercepts the offcanvas
|
|
292
|
+
`show` event and closes the host panel first, opening Settings once it has
|
|
293
|
+
finished sliding out; `_navbar.scss` releases the header lift, and raises
|
|
294
|
+
`#info-section` above it, for browsers without `:has()`. Covered by "Settings
|
|
295
|
+
opened from the nav menu paints ABOVE it" in
|
|
296
|
+
`test/visual/features/mobile-overlay-stacking.spec.js` (evidence:
|
|
297
|
+
[`test/visual/evidence/navbar-fit/`](test/visual/evidence/navbar-fit/README.md)
|
|
298
|
+
— `03-settings-stacking.png`: top element at the panel centre `a.nav-link`
|
|
299
|
+
→ the panel's own content; header `z-index` 1046 → 1030).
|
|
300
|
+
|
|
301
|
+
- **Section topic filters match whole tags, not substrings** — filtering a
|
|
302
|
+
section by a topic silently revealed posts that did not carry it. `data-tags`
|
|
303
|
+
was built as `tags | join: ' ' | slugify`, which slugifies *after* joining and
|
|
304
|
+
so turns the separators into hyphens — making a tag boundary indistinguishable
|
|
305
|
+
from a hyphen inside a slug — and the click handler then matched with
|
|
306
|
+
`String.includes`. Filtering `/news/technology/` by **ai** returned 6 cards
|
|
307
|
+
while the sidebar badge for that topic said 5, because a post tagged `edge-ai`
|
|
308
|
+
matched too. `_layouts/section.html` now slugifies each tag separately into a
|
|
309
|
+
space-separated list and matches whole tokens, so the rendered count always
|
|
310
|
+
agrees with the badge (which Liquid computes with exact `contains` membership).
|
|
311
|
+
Regression coverage in `test/visual/features/section-topic-controls.spec.js`
|
|
312
|
+
asserts token membership and pins the filtered count to the badge (evidence:
|
|
313
|
+
[`test/visual/evidence/section-topic-filter/`](test/visual/evidence/section-topic-filter/README.md)
|
|
314
|
+
— filtering /news/technology/ by "ai" showed 6 cards against a badge of 5, now
|
|
315
|
+
5; topics whose badge disagrees with what is shown: 2 → 0).
|
|
316
|
+
|
|
317
|
+
- **Nightly smoke tier is green again** — three `smoke` tests had been failing
|
|
318
|
+
every night since 2026-08-15 (the tier the PR gate does not run, so `main`
|
|
319
|
+
stayed green). Two were the topic-filter bug above; the third asserted the
|
|
320
|
+
sidebar's "All Articles" control only as an `<a href="#all-posts">`, but the
|
|
321
|
+
sidebar renders a `<button data-filter="all">` for the grid/list styles —
|
|
322
|
+
currently every section — so it could never pass. The topic-button selector
|
|
323
|
+
also used `.filter({ hasNot })`, which excludes elements *containing* a match
|
|
324
|
+
rather than matching elements themselves, so it selected the "All Articles"
|
|
325
|
+
button and asserted against an unfiltered list; it now uses `:not()`.
|
|
326
|
+
|
|
327
|
+
- **A rejected Anthropic credential now falls back to the next one** — the
|
|
328
|
+
translation pipeline picked the first credential that was *set* and never
|
|
329
|
+
reconsidered, so a revoked `CLAUDE_CODE_OAUTH_TOKEN` shadowed a working
|
|
330
|
+
`ANTHROPIC_API_KEY` and took the whole run down with a `401 OAuth access
|
|
331
|
+
token has been revoked`. `scripts/translate.rb` now treats 401/403 as a
|
|
332
|
+
credential failure rather than a request failure and retries with the next
|
|
333
|
+
configured credential, rebuilding the payload so the OAuth-only Claude Code
|
|
334
|
+
identity block is not sent with an API key. The switch is sticky, so a dead
|
|
335
|
+
credential costs one rejection per run rather than one per chunk.
|
|
336
|
+
|
|
337
|
+
- **A failed translation run no longer opens a PR containing nothing** —
|
|
338
|
+
`_data/i18n/manifest.yml` stamped `updated_at` on every save, so a run in
|
|
339
|
+
which *every* page failed still produced a one-line diff. That was enough
|
|
340
|
+
for `translate.yml` to open (and keep updating) a PR that read like a routine
|
|
341
|
+
translation refresh and contained no translations. The manifest is now
|
|
342
|
+
written only when the mapping itself changed; a partially successful run
|
|
343
|
+
still pushes the pages that succeeded, and the run still exits non-zero.
|
|
344
|
+
|
|
345
|
+
- **The cookbook is reachable from the navbar** — the `recipes` collection
|
|
346
|
+
(ZER0-084) shipped with a landing page at `/recipes/` that nothing linked to,
|
|
347
|
+
so the deployed cookbook could only be found by typing the URL.
|
|
348
|
+
`_data/navigation/main.yml` now carries a Recipes entry with the demo
|
|
349
|
+
recipes and the feature docs.
|
|
350
|
+
|
|
351
|
+
- **Section sidebars no longer emit dead sub-topic anchors** — the sidebar
|
|
352
|
+
produced `<a href="#tag">` for every tag, but the matching
|
|
353
|
+
`<section id="tag">` target exists only in the `magazine` branch of
|
|
354
|
+
`_layouts/section.html`, and only for the first 5 sub-categories that keep a
|
|
355
|
+
post once the featured hero is excluded. `grid` and `list` sections (and
|
|
356
|
+
`grid` is the default) therefore emitted one dead anchor per tag, and
|
|
357
|
+
`magazine` emitted them for tags 6–15 — 64 of them on this repo's own demo
|
|
358
|
+
site. Dead anchors are invalid markup, a dead click for keyboard/AT users,
|
|
359
|
+
and they left the sidebar scrollspy unable to activate. Anchors are now
|
|
360
|
+
emitted only where a target provably exists; every other style renders
|
|
361
|
+
`<button data-filter>`, which the layout's existing handler already wires to
|
|
362
|
+
the `[data-tags]` cards. The `list` branch gained the `data-tags` attribute
|
|
363
|
+
it was missing (without it those buttons would have been inert), and the
|
|
364
|
+
filter handler now applies pill colours only to actual pills, so the pills
|
|
365
|
+
and the sidebar stay in sync instead of fighting over each other's classes.
|
|
366
|
+
Regression cover: `test/visual/features/section-topic-controls.spec.js`
|
|
367
|
+
- **Consumer homepages no longer claim to be this theme** — the
|
|
368
|
+
`SoftwareApplication` JSON-LD in `_includes/content/jsonld-software.html` is
|
|
369
|
+
now opt-in via `jsonld_software_application` (set on this site only). The
|
|
370
|
+
block hardcodes this theme's RubyGems URL, GitHub repository, MIT licence,
|
|
371
|
+
feature list and author, but was wired unconditionally into every consumer's
|
|
372
|
+
homepage — so a consulting firm's site was telling search engines it was a
|
|
373
|
+
free open-source Ruby gem. Consumers need no action: absent config is falsey.
|
|
374
|
+
Evidence: [`test/visual/evidence/jsonld-software-optin/`](test/visual/evidence/jsonld-software-optin/README.md).
|
|
375
|
+
- **`audit-consumer` misread most consumers' theme mode** — `detect_consumer_mode()`
|
|
376
|
+
matched `^remote_theme:` with no tolerance for whitespace before the colon, so
|
|
377
|
+
the column-aligned YAML style that 6 of 9 fleet consumers use never matched and
|
|
378
|
+
every one of them was silently reported as `gem` mode. That skipped the plugin
|
|
379
|
+
checks entirely, with no warning that they had been skipped.
|
|
380
|
+
- **`audit-consumer --format json` emitted unparseable JSON** — every entry
|
|
381
|
+
carried a trailing comma, so the array always closed on `},\n]}`. The
|
|
382
|
+
human-readable log lines also went to stdout, mixing into the payload. Entries
|
|
383
|
+
are now comma-separated correctly and logging moves to stderr under
|
|
384
|
+
`--format json`, so the output pipes straight into `jq`.
|
|
385
|
+
- **`audit-consumer` ignored Jekyll's `source:`** — a consumer that relocates its
|
|
386
|
+
site tree (e.g. `source: pages`) was audited at the repo root, reporting a
|
|
387
|
+
falsely clean "no overrides, no unique files". It now follows `source:` for the
|
|
388
|
+
file scan while still reading config and `.theme-overrides.yml` from the root.
|
|
389
|
+
- **The Obsidian plugin was demanded of consumers that cannot run it** — the
|
|
390
|
+
manifest listed `_plugins/obsidian_links.rb` as required for every
|
|
391
|
+
`remote_theme` consumer, contradicting `obsidian.instructions.md`, which
|
|
392
|
+
documents it as opt-in and "skipped under the `github-pages` gem". GitHub Pages
|
|
393
|
+
builds in safe mode and loads no local plugins, so nothing the theme ships is
|
|
394
|
+
mandatory; `required_plugin_paths` is now empty and the plugin is optional.
|
|
395
|
+
|
|
396
|
+
### Changed
|
|
397
|
+
|
|
398
|
+
- **`_data/consumers.yml` now covers the whole fleet** — added `zer0-pages`,
|
|
399
|
+
`irony-works`, `wargames` and `zer0-pages-remote`, which were unregistered and
|
|
400
|
+
therefore invisible to `propagate.rb` in both directions (no release dispatch,
|
|
401
|
+
never in the drift report). The `it-journey` risk note was corrected: its
|
|
402
|
+
"~55 shadowed files / ~75 lines of !important CSS working around #338" claim
|
|
403
|
+
is not supported by `audit-consumer` — only 2 files shadow a theme file, the
|
|
404
|
+
CSS is 31 lines in this theme's own documented `user_overrides` hook, and no
|
|
405
|
+
fix numbered #338 could be substantiated in that repo.
|
|
406
|
+
|
|
407
|
+
## [1.28.0](https://github.com/bamr87/zer0-mistakes/compare/v1.27.0...v1.28.0) (2026-08-09)
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
### Features
|
|
411
|
+
|
|
412
|
+
* **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))
|
|
413
|
+
* **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))
|
|
414
|
+
* **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))
|
|
415
|
+
* **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))
|
|
416
|
+
* **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))
|
|
417
|
+
* **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))
|
|
418
|
+
* **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))
|
|
419
|
+
* **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))
|
|
420
|
+
* **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))
|
|
421
|
+
* **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))
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
### Bug Fixes
|
|
425
|
+
|
|
426
|
+
* **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))
|
|
427
|
+
* **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))
|
|
428
|
+
* **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))
|
|
429
|
+
* **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))
|
|
430
|
+
* **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))
|
|
431
|
+
* **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))
|
|
432
|
+
* **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))
|
|
433
|
+
* **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))
|
|
434
|
+
|
|
435
|
+
## [Unreleased]
|
|
436
|
+
|
|
437
|
+
### Fixed
|
|
438
|
+
|
|
439
|
+
- **The skip link never moved keyboard focus (#278)** — `_layouts/root.html`
|
|
440
|
+
rendered `<main id="main-content">` with no `tabindex`, and `<main>` is not natively focusable, so activating "Skip to main content" scrolled the page while focus stayed on `<body>`: the next `Tab` returned the user to the header nav they had just skipped. That defeats WCAG 2.4.1 (Bypass Blocks) on every consuming site, and the theme's own docs already prescribed the fix (`skip-to-content.md` → *Focus Not Moving* → "Add `tabindex=\"-1\"` to target") while the shipped layout omitted it. Now `<main id="main-content" tabindex="-1">`, paired with `#main-content:focus { outline: none; }` in `_sass/utilities/_focus.scss` so the container does not paint a ring — descendants keep theirs, and the rule is safe only because `-1` keeps the container out of the sequential `Tab` order. Measured across all three engines: focus lands on `#main-content` in Chromium, Firefox **and WebKit** (the engine the report named), where before it moved in none of them. The stale `<div id="main-content">` example in the English and French docs now matches the shipped markup.
|
|
441
|
+
- **Seven theme dialogs labelled themselves with a bare `<h5>`** — the search
|
|
442
|
+
modal, cookie settings modal, statistics help modal and the settings / background / section / admin offcanvases each opened with `<h5 class="modal-title">` or `<h5 class="offcanvas-title">`, so anyone navigating by heading met a level-5 heading as the dialog's title, skipping h3 and h4. Six other dialogs already used the correct `<h2 class="…-title h5">` form, so the theme contradicted itself half the time. All seven now match. `.h5` reproduces the exact sizing, so the change is visually inert. `_includes/docs/bootstrap-docs.html` and the docs prose examples are deliberately untouched — they reproduce upstream Bootstrap's own markup and should keep doing so. (evidence: [`test/visual/evidence/dialog-heading-levels/`](test/visual/evidence/dialog-heading-levels/README.md) — heading walk h2 → h5 becomes h2 → h2 on all six live dialogs, renders byte-identical)
|
|
443
|
+
- **Cookie modal's "Your Privacy Rights" list was invisible in dark mode** — the
|
|
444
|
+
list used Bootstrap's fixed `text-dark` utility inside a `bg-body` panel. `.text-dark` resolves to `rgba(var(--bs-dark-rgb), 1)`, and `--bs-dark-rgb` is **not** remapped by `[data-bs-theme=dark]` — it stays `33,37,41`, which is byte-for-byte the dark `--bs-body-bg` (`#212529`). Measured in a browser: **1.00:1**, against WCAG 1.4.3 (AA)'s 4.5:1 minimum. Not "hard to read" — the same colour as its background, on the one dialog a visitor is most likely forced to read, in the theme's default colour mode, shipped to every consumer. Now `text-body` (**11.85:1** dark, 15.43:1 light, unchanged). `.cookie-category`'s hardcoded `#dee2e6` border became `var(--bs-border-color)`, which is the identical colour in light mode and a visible one in dark. A regression test opens the dialog and asserts the measured contrast ratio — `axe` cannot catch this class of bug on this theme, because the skin system's `body::after` background image makes axe report every contrast check in the dialog as `incomplete` rather than a violation. (evidence: [`test/visual/evidence/cookie-consent-contrast/`](test/visual/evidence/cookie-consent-contrast/README.md) — dark-mode contrast 1.00:1 → 11.85:1, light mode unchanged)
|
|
445
|
+
- **`--page` lookups never matched a real Giscus thread** — `normalize_page()`
|
|
446
|
+
prepended a leading slash to build the discussion title, but Giscus's `pathname` mapping searches for `location.pathname` with the leading slash **removed** (verified live: `/posts/2025/01/21/remote-work-revolution/` requests `term=posts/2025/01/21/remote-work-revolution/`). So `seed` created discussions Giscus would never find, and `thread`/`draft`/`post --page` missed every thread Giscus created itself — the entire "build conversations from page comments" workflow was inoperable against real data. Lookups now match all four title spellings (with/without leading and trailing slash) so both new and legacy/hand-made threads resolve.
|
|
447
|
+
- **`discussion_number_for_page` silently ignored pagination** — the query
|
|
448
|
+
declared `$after` and selected `pageInfo`, but never used either, so on a site with more than 100 discussions no thread past the first page could ever be found. Now uses `gh api graphql --paginate`.
|
|
449
|
+
- **`set -e` aborted the script on the success path** — `[[ -z "$NUMBER" ]] &&
|
|
450
|
+
error ...` as the last statement of a branch returns 1 when the lookup *succeeds*, which `set -e` turned into a silent exit with no output at all. Latent and unreachable while lookups always failed; the fix above exposed it immediately. Rewritten as `if` blocks in `resolve_number_arg` and `cmd_post`.
|
|
451
|
+
- **Giscus comments were broken sitewide** — every page rendering the comment
|
|
452
|
+
widget showed `An error occurred: giscus is not installed on this repository` instead of a comment box, on `zer0-mistakes.com` and locally, because the [giscus GitHub App](https://github.com/apps/giscus) was never installed on the repository. The `_config.yml` values were all correct (`data-repo-id` and `data-category-id` both verified against the live GitHub API, repo public, Discussions enabled, `Announcements` category), which is exactly why it went unnoticed: **no check in the repo could see it**. The `Giscus Comments Configuration` core test only inspects config keys and Liquid, and `test/visual/features/comments.spec.js` stubs `giscus.app/client.js` out entirely — so all 16 core tests passed at 100% against a completely non-functional feature. **Resolved**: the app is now installed and `doctor` reports the chain healthy; comments render and accept sign-in on production. Verified with a seeded demo thread ([#379](https://github.com/bamr87/zer0-mistakes/discussions/379)) that the widget correctly resolves and displays.
|
|
453
|
+
- **Docs claimed the widget "won't load on localhost"** — it does. Giscus keys
|
|
454
|
+
off the `data-repo` attribute, not the page origin, so the iframe renders and reports real errors locally. The false claim told developers to expect a non-working widget in dev, which is precisely what hid this bug. `pages/_docs/features/giscus-comments.md` now documents localhost as a genuine end-to-end check, with a table mapping each rendered state to its cause.
|
|
455
|
+
|
|
456
|
+
### Added
|
|
457
|
+
|
|
458
|
+
- **`giscus-discussions doctor`** — a new subcommand that verifies the entire
|
|
459
|
+
comment chain end-to-end: repository public, Discussions enabled, `giscus.enabled: true`, `data-repo-id` actually belonging to this repo (the fork trap), `data-category-id` resolving to a real category, and — the part nothing else could check — whether the giscus GitHub App is installed, by asking the Giscus API itself. Exits non-zero with a specific remediation line per failure.
|
|
460
|
+
- **Giscus health check in CI** — `.github/workflows/giscus-digest.yml` (already
|
|
461
|
+
scheduled weekly) now runs `doctor` and fails the job with a summary when comments are down, so a sitewide comment outage surfaces on its own instead of waiting for a reader to report it.
|
|
462
|
+
- **Troubleshooting: "The giscus app is not installed"** — a new section in the
|
|
463
|
+
feature docs with captured screenshots of both the broken widget and the giscus.app configurator rejecting the repo, an explanation of why this step is uniquely easy to skip, a fork-specific warning, and a copy-pasteable `curl` health check.
|
|
464
|
+
- **Obsidian graph frontend revamp** — the graph views now mirror the Obsidian
|
|
465
|
+
desktop experience. The full graph page gains a floating **Graph settings**
|
|
466
|
+
card (Filters / Display / Forces): search with `tag:`/`path:` operators,
|
|
467
|
+
per-collection toggles generated from the wiki-index (count badge + color
|
|
468
|
+
swatch, doubling as the legend), show-orphans and show-unresolved switches,
|
|
469
|
+
node-size / link-thickness / label-fade sliders, repel-force and
|
|
470
|
+
link-distance sliders with animated re-layout, plus a zoom / fit / fullscreen
|
|
471
|
+
button stack, an Obsidian-style hover preview card, live dark-mode restyling,
|
|
472
|
+
and localStorage persistence. The local graph panel gains a depth selector
|
|
473
|
+
(1–3) and outgoing/incoming direction switches that re-render the subgraph in
|
|
474
|
+
place. Same vendored cytoscape.js, unchanged `wiki-index.json` contract
|
|
475
|
+
(evidence:
|
|
476
|
+
[`test/visual/evidence/obsidian-graph-revamp/`](test/visual/evidence/obsidian-graph-revamp/README.md);
|
|
477
|
+
regression: `test/visual/features/obsidian-graph.spec.js`).
|
|
478
|
+
|
|
479
|
+
- **Theme-canary reporting contract** (`docs/systems/theme-canary-contract.md`) —
|
|
480
|
+
the canonical upstream bug-intake protocol for downstream theme-scout agents
|
|
481
|
+
(it-journey, lifehacker.dev): required `theme-canary` + `from-<consumer>`
|
|
482
|
+
labels, a deterministic 12-hex dedupe key + hidden body marker, the mandated
|
|
483
|
+
open-AND-closed pre-filing search, a 5-issues-per-consumer-per-run cap, and a
|
|
484
|
+
required evidence format that records the theme version/commit observed (so
|
|
485
|
+
fixed-in-release triage is mechanical). Ships with the matching
|
|
486
|
+
`theme-canary.yml` issue form.
|
|
487
|
+
|
|
488
|
+
### Fixed
|
|
489
|
+
|
|
490
|
+
- **Mobile navigation opened as an unusable 60px sliver in the Swerve of Shore
|
|
491
|
+
example.** Its skin set `backdrop-filter` on `.navbar` for a frosted sticky
|
|
492
|
+
header, which — per the CSS spec, alongside `transform`/`filter`/`perspective`
|
|
493
|
+
— makes that element the containing block for its `position: fixed`
|
|
494
|
+
descendants. The theme's main-nav panel (`#bdNavbar`, an `.offcanvas-lg`) is
|
|
495
|
+
one, so it sized itself against the 60px navbar instead of the viewport:
|
|
496
|
+
tapping the hamburger dimmed the page and showed a bare title bar with **0 of
|
|
497
|
+
14 navigation links** reachable. The effect now lives on a `.navbar::before`
|
|
498
|
+
pseudo-element — visually identical, not an ancestor — restoring the
|
|
499
|
+
full-height panel with **14 of 14** links (evidence:
|
|
500
|
+
[`test/visual/evidence/mobile-nav-containing-block/`](test/visual/evidence/mobile-nav-containing-block/README.md)
|
|
501
|
+
— panel 60px → 780px at 390 and 768). A new smoke-tier spec
|
|
502
|
+
(`test/visual/features/mobile-nav-containing-block.spec.js`) guards the
|
|
503
|
+
invariant on the theme and names the offending ancestor when it fails.
|
|
504
|
+
|
|
505
|
+
- **The example's home and blog pages overflowed and ran edge-to-edge on
|
|
506
|
+
phones.** Their feed grid used Bootstrap's `.row` gutters without a container
|
|
507
|
+
to absorb the −12px margins, making the page 13px wider than the screen, and
|
|
508
|
+
neither section carried an inline padding, so 15 of 30 text blocks sat flush
|
|
509
|
+
against the bezel. Now `gx-0 gy-4` plus a 0.75rem mobile gutter matching the
|
|
510
|
+
theme's own 12px inset — zero horizontal overflow at 320–768, banner still
|
|
511
|
+
full-bleed.
|
|
512
|
+
|
|
513
|
+
- **GitHub Pages production deploy no longer fails at all — the site had been
|
|
514
|
+
frozen since 2026-08-05.** Three independent faults, each of which aborted the
|
|
515
|
+
whole production `jekyll build`, so nothing published after #346:
|
|
516
|
+
1. `_layouts/collection.html` sorted `site[page.collection]` without checking
|
|
517
|
+
it resolved. A page can select this layout in front matter while living
|
|
518
|
+
outside any collection, making that lookup `nil`; Liquid's `sort` then
|
|
519
|
+
raises `Cannot sort a null object.` and kills the *entire* build, not just
|
|
520
|
+
the page. It now falls back to an empty list.
|
|
521
|
+
2. `scripts/translate.rb` copied `layout: collection` into the flat `fr/**`
|
|
522
|
+
tree, which is exactly the misconfiguration above — `fr/docs/index.md` was
|
|
523
|
+
the page that took the site down. Collection-only layouts are now dropped
|
|
524
|
+
from generated translations so the `path: fr` default (`layout: default`)
|
|
525
|
+
applies, and the affected page is regenerated.
|
|
526
|
+
3. `CHANGELOG.md` is a published page (`/CHANGELOG/`), so its prose is parsed
|
|
527
|
+
as Liquid. Two entries quoted Liquid tags without a `raw` guard; one of
|
|
528
|
+
them genuinely executed `include_relative` on `_config.yml`, which in turn
|
|
529
|
+
tripped over a literal `mermaid` tag written inside a config comment.
|
|
530
|
+
Both entries are now guarded and the config comment no longer spells the
|
|
531
|
+
tag out.
|
|
532
|
+
|
|
533
|
+
- **Production builds are now verified before merge.** `.github/workflows/pages.yml`
|
|
534
|
+
builds (never deploys) on pull requests. No other job ran `jekyll build`
|
|
535
|
+
against the production config, which is why all three faults above reached
|
|
536
|
+
`main` with CI green.
|
|
537
|
+
|
|
538
|
+
- **GitHub Pages production deploy no longer fails on the translated config
|
|
539
|
+
page.** The admin config utility `pages/_about/settings/config.md` embeds a
|
|
540
|
+
raw `_config.yml` dump via {% raw %}`{% include_relative _config.yml %}`{% endraw %}, but the
|
|
541
|
+
translation pipeline copied the page into `fr/about/settings/` without its
|
|
542
|
+
sibling data file, so the production `github-pages` build died with
|
|
543
|
+
`Could not locate the included file '_config.yml'`. The page is now excluded
|
|
544
|
+
from translation (`translation.exclude` in `_config.yml`) — it has no
|
|
545
|
+
prose to translate anyway — and the stale `fr/about/settings/config.md` plus
|
|
546
|
+
its `_data/i18n/manifest.yml` entry are removed.
|
|
547
|
+
- **Translation runs no longer break the `oneline` check.** `scripts/translate.rb`
|
|
548
|
+
writes whatever the provider returns, and a provider is free to soft-wrap a
|
|
549
|
+
translated paragraph across several lines — no prompt instruction reliably
|
|
550
|
+
prevents it. Wrapped prose then landed in `fr/**`, turned
|
|
551
|
+
`markdown-oneline.yml` red on the translation PR, and stayed red on `main`
|
|
552
|
+
after it merged. Two of the currently committed translations were in exactly
|
|
553
|
+
that state.
|
|
554
|
+
- `translate.rb` now normalises every page it writes through
|
|
555
|
+
`tools/unwrap-prose.py` — the same tool CI runs, so the rule has one source
|
|
556
|
+
of truth instead of a reimplementation that could drift. Best-effort: a
|
|
557
|
+
missing `python3` warns rather than failing an otherwise good run.
|
|
558
|
+
- `.github/workflows/translate.yml` runs the same tool as a guaranteed
|
|
559
|
+
backstop immediately before committing, then `--check`s its own work so a
|
|
560
|
+
silent failure cannot just move the breakage to the PR's CI run.
|
|
561
|
+
- The tool is resolved relative to `translate.rb` rather than `--root`;
|
|
562
|
+
`--root` points at the content tree being translated, so the previous
|
|
563
|
+
lookup missed the tool whenever the two differed.
|
|
564
|
+
- Unwrapped the two affected files, so `oneline` passes on `main` again.
|
|
565
|
+
- Regression test in `test/test_i18n.sh` backed by a new `stub-wrap`
|
|
566
|
+
provider that soft-wraps at 40 columns. Asserting "output is unwrapped"
|
|
567
|
+
against the plain stub would have passed whether or not normalisation ran.
|
|
568
|
+
|
|
569
|
+
### Added
|
|
570
|
+
|
|
571
|
+
- **`examples/` — self-contained demo sites built on the theme.** New top-level
|
|
572
|
+
directory (excluded from the theme's own site build and from the gem) for
|
|
573
|
+
complete Jekyll sites that show the theme configured for a particular kind of
|
|
574
|
+
site. Each has its own `_config.yml`, `Gemfile`, and content, and builds
|
|
575
|
+
against the local theme sources via `_config_dev.yml`.
|
|
576
|
+
- `examples/swerve-of-shore/` — **Swerve of Shore**, a serialized literary
|
|
577
|
+
reading blog rebuilt from
|
|
578
|
+
[swerveofshore.com](https://www.swerveofshore.com/) with the site owner's
|
|
579
|
+
permission. 52 pages, 0 broken internal links. Exercises a `series` output
|
|
580
|
+
collection with nested per-section paths, a data-driven taxonomy
|
|
581
|
+
(`_data/episodes.yml`) that generates the sidebar rail, the episode
|
|
582
|
+
schedule with live entry counts, and a section page for every node — so a
|
|
583
|
+
nav target resolves even where nothing is written yet. Also covers article
|
|
584
|
+
hero images (`show_hero`), entries ordered by number rather than date, the
|
|
585
|
+
shared `post-card` component in a single-column feed, and a full editorial
|
|
586
|
+
light-mode restyle done entirely through `assets/css/user-overrides.css` —
|
|
587
|
+
no theme files touched. The site's identity, taxonomy, entry titles/dates,
|
|
588
|
+
and featured images are reproduced, along with a short quoted excerpt per
|
|
589
|
+
entry (the opening the original publishes in its own RSS feed), attributed
|
|
590
|
+
and linked back. The essays themselves are not reproduced.
|
|
591
|
+
- `examples/README.md` — how to run one and the conventions for adding
|
|
592
|
+
another.
|
|
593
|
+
- **Theme propagation system — releases now reach the sites built on them.**
|
|
594
|
+
Releasing ended at RubyGems; nothing told the five downstream consumers a new
|
|
595
|
+
version existed, so all three pinned sites were still on v1.26.0 when v1.27.0
|
|
596
|
+
shipped and the two unpinned ones had been silently tracking `main`.
|
|
597
|
+
- `_data/consumers.yml` — registry of every consumer, its consumption mode
|
|
598
|
+
(`remote_theme_pinned` / `remote_theme_floating` / `gem` / `path`), and every
|
|
599
|
+
file that holds a version pin.
|
|
600
|
+
- `scripts/propagate.rb` — reports pin drift across the registry
|
|
601
|
+
(`--format text|json|github`, `--strict`) or dispatches a `theme-release`
|
|
602
|
+
event to each consumer (`--dispatch`).
|
|
603
|
+
- `.github/workflows/propagate-theme.yml` — dispatches on release publish;
|
|
604
|
+
weekly drift report. Never pushes to a consumer: each one opens its own PR so
|
|
605
|
+
its own CI gates the bump.
|
|
606
|
+
- `templates/consumer/` — the consumer's half of the contract:
|
|
607
|
+
`bump-theme-pins.sh` (rewrites `remote_theme`, `theme_repo`, and Gemfile gem
|
|
608
|
+
constraints in one pass; `--check`, `--dry-run`, `--latest`, `--pin`),
|
|
609
|
+
`theme-bump.yml` (dispatch + weekly schedule + manual), and a
|
|
610
|
+
`.theme-overrides.yml` starter. The schedule matters most for gem-mode
|
|
611
|
+
consumers, which have no `remote_theme` and so pick up nothing automatically.
|
|
612
|
+
- `docs/systems/theme-propagation.md` — how the whole flow fits together.
|
|
613
|
+
- **`./scripts/bin/manifest --check`** — verifies the committed theme manifest
|
|
614
|
+
matches the working tree, ignoring `generated_at`. `--dry-run` now emits only
|
|
615
|
+
YAML on stdout (progress logs moved to stderr) so its output can be diffed
|
|
616
|
+
directly.
|
|
617
|
+
- **Consumer extension hooks (`_includes/custom/`).** Four empty stubs the
|
|
618
|
+
chrome now includes at fixed points — `custom/head.html` (end of `<head>`),
|
|
619
|
+
`custom/body-start.html` (right after `<body>`, e.g. GTM noscript),
|
|
620
|
+
`custom/footer.html` (after the theme footer), `custom/body-end.html` (last
|
|
621
|
+
thing before `</body>`). A consumer site shadows just the stub to inject
|
|
622
|
+
JSON-LD, fonts, verification tags, or scripts — no more forking
|
|
623
|
+
`core/head.html`/`root.html` and drifting from the theme. Documented in
|
|
624
|
+
`_includes/README.md`.
|
|
625
|
+
- **`components/card-grid.html` + `components/data-card.html`.** A generic,
|
|
626
|
+
data-driven card grid (title/url/icon/badge/meta-pills/buttons schema) for
|
|
627
|
+
org hub dashboards, fleet registries, service grids, and link boards —
|
|
628
|
+
the markup consumer sites have been hand-rolling per page. Includes an
|
|
629
|
+
optional empty-state message.
|
|
630
|
+
- **`_layouts/404.html` — the 404 page as a theme layout.** The full 404
|
|
631
|
+
experience (including the unconfigured-site setup guide) now lives in the
|
|
632
|
+
theme; a consumer's `/404.html` shrinks from a 224-line vendored copy to a
|
|
633
|
+
4-line front-matter stub (`layout: "404"`). Setup mode is branded with
|
|
634
|
+
`site.title` instead of a hardcoded theme welcome, and the stub page's body
|
|
635
|
+
renders below the standard content for site-specific additions.
|
|
636
|
+
- **`color_mode_lock` config.** Pin the site to one color mode: visitor
|
|
637
|
+
preference and OS scheme are ignored, the light/dark/auto switcher is
|
|
638
|
+
removed, and `core/color-mode-init.html` + `halfmoon.js` enforce the lock
|
|
639
|
+
pre-paint. Replaces consumer JS workarounds that re-asserted a mode on every
|
|
640
|
+
`matchMedia` change.
|
|
641
|
+
- **PostHog privacy options** (`posthog.privacy.*`): `respect_gpc` (honor the
|
|
642
|
+
Global Privacy Control signal alongside DNT, default on), `require_consent`
|
|
643
|
+
(start opted out with memory-only persistence until the visitor accepts the
|
|
644
|
+
cookie-consent "analytics" category), and `geoip_disable` (no IP→location
|
|
645
|
+
resolution). Upstreams the deltas consumer sites were maintaining in a
|
|
646
|
+
full fork of `analytics/posthog.html`.
|
|
647
|
+
- **`news:` config surface for the news/section layouts.** `category_base`
|
|
648
|
+
(e.g. `/categories/` instead of the hardcoded `/news/`), `index_url`,
|
|
649
|
+
`hero: false`, `archives_url`, and a `newsletter` block (endpoint-or-mailto,
|
|
650
|
+
or hidden entirely — the old markup shipped a form that submitted nowhere).
|
|
651
|
+
|
|
652
|
+
### Changed
|
|
653
|
+
|
|
654
|
+
- **The news/section layouts work with zero `_data`.** Section navigation
|
|
655
|
+
falls back from `_data/navigation/posts.yml` to `site.categories`; the hero
|
|
656
|
+
falls back to the newest post when nothing is marked `breaking`/`featured`;
|
|
657
|
+
tags links render only when a tags page exists (honoring `site.tags_page`);
|
|
658
|
+
archive month links render only when an archives page exists. A data-less
|
|
659
|
+
consumer now gets a fully working magazine homepage instead of empty chrome
|
|
660
|
+
and 404 links.
|
|
661
|
+
- **Zero-`_data` resilience across components.** The skin quick-select and
|
|
662
|
+
theme customizer fall back to the compiled skin registry when
|
|
663
|
+
`_data/theme_skins.yml` is absent; the page-feedback widget falls back to a
|
|
664
|
+
generic four-type taxonomy when `_data/feedback_types.yml` is absent; the
|
|
665
|
+
landing get-started band (theme install cards) renders only when the site
|
|
666
|
+
ships a `landing.get_started` block — a data-less consumer no longer
|
|
667
|
+
advertises the theme's own install methods.
|
|
668
|
+
- **`home` layout accepts `hide_intro` as an alias of `hide_title`**, matching
|
|
669
|
+
the flag other layouts use for "suppress the generated page header".
|
|
670
|
+
- **`halfmoon.js` honors `color_mode_default`.** The switcher no longer
|
|
671
|
+
overrides the configured default with the OS preference on first visit
|
|
672
|
+
(previously the page could flip modes right after load).
|
|
673
|
+
- The default skin fallback is now `air` everywhere (`root.html`,
|
|
674
|
+
controls bar, customizer) — `dark` was never a compiled skin, so the old
|
|
675
|
+
fallback selected a skin that doesn't exist.
|
|
676
|
+
|
|
677
|
+
### Fixed
|
|
678
|
+
|
|
679
|
+
- **`_data/theme-manifest.yml` was 13 minors stale.** It sat at `1.14.0` while
|
|
680
|
+
the theme shipped to `1.27.0`, so every SHA-256 in it was wrong and
|
|
681
|
+
`scripts/bin/audit-consumer` — which reads it to classify consumer files —
|
|
682
|
+
silently compared against a June snapshot. Root cause: the file's header said
|
|
683
|
+
it regenerated during `scripts/bin/release`, but release-please became the
|
|
684
|
+
canonical release path and knows nothing about it. Regenerated, and now held
|
|
685
|
+
current by a CI gate (`version.rb` ↔ manifest version) plus
|
|
686
|
+
`manifest-sync.yml`, which regenerates it inside the release PR.
|
|
687
|
+
- **`test/fixtures/consumer-gem/_layouts/default.html` had drifted from the
|
|
688
|
+
theme layout it mirrors**, so the "`--fix` deletes IDENTICAL files" audit test
|
|
689
|
+
had been failing since the layout changed in #310 — the fixture was being
|
|
690
|
+
classified `DIFFERS_UNJUSTIFIED` rather than `IDENTICAL`, testing the opposite
|
|
691
|
+
of its intent. Re-synced; the audit suite is green again (21/21).
|
|
692
|
+
- **Mobile overlays no longer trap under the page chrome.** The
|
|
693
|
+
`.zer0-bg-body` background utility isolates the body stacking context and
|
|
694
|
+
pushes the noise overlay to `z-index: -1` instead of force-elevating every
|
|
695
|
+
direct child (`position: relative; z-index: 1`). That old rule made `<main>`
|
|
696
|
+
a stacking context that (a) capped the docs-sidebar offcanvas below the
|
|
697
|
+
fixed header — its close button was unreachable on mobile — and (b) beat
|
|
698
|
+
FAB `position: fixed` rules on specificity, dropping them into flow and
|
|
699
|
+
adding 16px of horizontal scroll on content pages.
|
|
700
|
+
- **Main-nav offcanvas paints above its backdrop on mobile.** The fixed header
|
|
701
|
+
is lifted over Bootstrap's body-level backdrop only while `#bdNavbar` is
|
|
702
|
+
opening/open/closing, so the menu is actually tappable instead of rendering
|
|
703
|
+
dimmed behind the backdrop.
|
|
704
|
+
- **The unified drawer's Search button works.** It targeted `#search-modal`
|
|
705
|
+
but the modal's id is `#siteSearchModal`; it now uses the shared
|
|
706
|
+
`data-search-toggle` binding, which also closes the drawer before opening
|
|
707
|
+
search.
|
|
708
|
+
- The measured header height is published as `--zer0-header-height` on
|
|
709
|
+
`:root` (set by `auto-hide-nav.js`), so stylesheets can align overlays with
|
|
710
|
+
the real header instead of hard-coding its pixel height.
|
|
711
|
+
|
|
712
|
+
### Added
|
|
713
|
+
|
|
714
|
+
- **ABC board books (`book-abc` layout) — the "ABC & Language" series.** A new
|
|
715
|
+
immersive, single-scroll toddler alphabet layout (`_layouts/book-abc.html`)
|
|
716
|
+
driven entirely by an `alphabet:` front-matter list — one big letter, one
|
|
717
|
+
word, one picture per card, with A–Z quick-jump anchors and a cover hero.
|
|
718
|
+
The big letter is HTML typography (never baked into the art), and a card
|
|
719
|
+
whose plate is still `planned` shows a tinted "illustration coming soon"
|
|
720
|
+
placeholder so a book reads end-to-end before any art renders. New
|
|
721
|
+
`_includes/components/abc-letter.html` renders each card; `_sass/components/_book.scss`
|
|
722
|
+
gains `.abc-board` / `.abc-letter-*` styles plus a `.abc-style--<id>` skin per
|
|
723
|
+
shared art-style id. `components/bookshelf.html` now lists both `book` and
|
|
724
|
+
`book-abc` books, grouped into series shelves from `_data/series.yml`;
|
|
725
|
+
`book-card.html` shows a letter count for ABC books. Ships a demo book
|
|
726
|
+
(`pages/_books/abc-demo/`) + default series metadata (`_data/series.yml`).
|
|
727
|
+
Regression test [`test/visual/features/book-abc.spec.js`](test/visual/features/book-abc.spec.js)
|
|
728
|
+
and before/after evidence in
|
|
729
|
+
[`test/visual/evidence/book-abc/`](test/visual/evidence/book-abc/). Docs:
|
|
730
|
+
[`docs/features/abc-books.md`](docs/features/abc-books.md).
|
|
731
|
+
- **`nav: pages` sidebar mode — auto-build the left tree from page URLs.** A new
|
|
732
|
+
sidebar mode (`_includes/navigation/sidebar-pagetree.html`) derives a
|
|
733
|
+
collapsible section tree purely from page permalinks under a `sidebar.base`
|
|
734
|
+
prefix — no curated `_data/navigation/*.yml` file to write or keep in sync.
|
|
735
|
+
Enable per page / collection / site with `sidebar: {nav: pages, base: /docs/,
|
|
736
|
+
order_by: nav_order, title: …}`. It covers plain pages (`site.html_pages`) and
|
|
737
|
+
collection documents (`site.documents`) alike, groups them by first path
|
|
738
|
+
segment, humanizes section labels from the URL (never leaking a generic
|
|
739
|
+
"Index" title), sorts each section by a numeric `order_by` (natural order),
|
|
740
|
+
supports per-page `sidebar_label` / `sidebar_exclude`, and marks only the
|
|
741
|
+
current page active with its section expanded server-side — pure Liquid, so
|
|
742
|
+
it is GitHub Pages / `remote_theme` safe. Documented at
|
|
743
|
+
`/docs/features/sidebar-page-tree/`.
|
|
744
|
+
- **Claude Code OAuth in the AI installer** — the spec-driven installer
|
|
745
|
+
(`scripts/bin/install`) is now multi-provider. `scripts/install/ai/client.sh`
|
|
746
|
+
resolves a provider via `ZER0_AI_PROVIDER` (default `auto`), preferring the
|
|
747
|
+
logged-in `claude` CLI (**Claude Code OAuth** — zero key handling), then the
|
|
748
|
+
Anthropic Messages API (`CLAUDE_CODE_OAUTH_TOKEN` OAuth bearer or
|
|
749
|
+
`ANTHROPIC_API_KEY`), then OpenAI. `install doctor` reports the active
|
|
750
|
+
provider; `--ai-provider` / `--ai-model` / `ZER0_AI_MODEL` tune it; `--no-ai`
|
|
751
|
+
/ `ZER0_NO_AI=1` disable it. User context is sanitized before every call.
|
|
752
|
+
- **Config-file layer for the installer** — new `scripts/install/config.sh`
|
|
753
|
+
discovers and merges `~/.config/zer0/install.yml`, `<target>/zer0.install.yml`,
|
|
754
|
+
`<target>/.zer0/config.yml`, and `--config FILE` (precedence:
|
|
755
|
+
defaults < profile < config < env < flags). Recognises site / github / theme /
|
|
756
|
+
deploy / agents / tasks / ai keys; API keys stay environment-only.
|
|
757
|
+
- **`install suggest`** subcommand — recommend a profile + deploy target
|
|
758
|
+
(AI-assisted with rule-based fallback) — plus `--yes` as an alias for
|
|
759
|
+
`--auto-accept`.
|
|
760
|
+
- Installer regression matrix (`test/test_installer.sh`) now covers AI
|
|
761
|
+
provider resolution, text extraction across provider shapes, the config-file
|
|
762
|
+
layer + precedence, and the `doctor` AI check (all offline).
|
|
763
|
+
|
|
764
|
+
### Changed
|
|
765
|
+
|
|
766
|
+
- Installer spec default `ai.provider` is now `auto` (was `openai`); the AI
|
|
767
|
+
wizard records the provider that actually served the run.
|
|
768
|
+
- **CI workflows now honor `CLAUDE_CODE_OAUTH_TOKEN`** — `ui-audit.yml`,
|
|
769
|
+
`ai-content-review.yml`, and `ci-self-repair.yml` previously gated their
|
|
770
|
+
Claude Code agent tier on `ANTHROPIC_API_KEY` alone, silently ignoring a
|
|
771
|
+
configured OAuth token. They now follow the same house convention as
|
|
772
|
+
`claude.yml` / `issue-autopilot.yml`: `CLAUDE_CODE_OAUTH_TOKEN` preferred,
|
|
773
|
+
`ANTHROPIC_API_KEY` used only when it's absent.
|
|
774
|
+
|
|
775
|
+
### Fixed
|
|
776
|
+
|
|
777
|
+
- **Left-sidebar nav highlighted every item as "active".** `nav-tree.html`
|
|
778
|
+
used {% raw %}`{% assign is_active = page.url == item.url %}`{% endraw %}, but Liquid `assign`
|
|
779
|
+
does not evaluate `==` — it stored `page.url` (always truthy), so every link
|
|
780
|
+
rendered with the active style. Replaced the three broken assigns
|
|
781
|
+
(`is_active`, `child_active`, `gc_active`) with proper conditional assigns so
|
|
782
|
+
only the current page is marked active.
|
|
783
|
+
- **`install deploy` no longer clobbers site content.** `spec_write` treated an
|
|
784
|
+
empty `SPEC_TASKS` as "use the full default task list", so a deploy-only run
|
|
785
|
+
re-ran `config`/`pages`/`nav` and overwrote a customised `_config.yml`,
|
|
786
|
+
`index.md`, and navigation. Empty now serialises to `[]`; `deploy` is
|
|
787
|
+
deploy-only and also skips agent-file rewrites.
|
|
788
|
+
- **github-pages / remote profile emitted a broken `remote_theme`.** The remote
|
|
789
|
+
`_config.yml` template resolved `{% raw %}{{GITHUB_REPO}}{% endraw %}` to the *site's* repo; it now
|
|
790
|
+
uses a dedicated `{% raw %}{{THEME_REMOTE}}{% endraw %}` variable (default `bamr87/zer0-mistakes`,
|
|
791
|
+
overridable via `THEME_REMOTE`).
|
|
792
|
+
- **Deploy workflow templates had unsubstituted variables.** Added
|
|
793
|
+
`{% raw %}{{DEFAULT_BRANCH}}{% endraw %}`, `{% raw %}{{RUBY_VERSION}}{% endraw %}`, and `{% raw %}{{SITE_NAME}}{% endraw %}` to the template
|
|
794
|
+
renderer, so the generated `jekyll-gh-pages.yml` (and docker-prod/azure-swa
|
|
795
|
+
artifacts) no longer contain literal `{% raw %}{{…}}{% endraw %}` tokens. Regression tests assert
|
|
796
|
+
no unresolved tokens survive in any deploy artifact.
|
|
797
|
+
- **Agent files were written twice** when `agents` appeared in both the task
|
|
798
|
+
list and `SPEC_AGENTS`; `apply.sh` now runs the agents task at most once.
|
|
799
|
+
- **The remote / github-pages Gemfile failed to build on Ruby 3.x.** It paired
|
|
800
|
+
the legacy `github-pages` gem with a standalone `jekyll-remote-theme`, which
|
|
801
|
+
bundler resolved to an ancient github-pages 170 (Jekyll 3.6 / kramdown 1.14,
|
|
802
|
+
`rexml` LoadError). The remote Gemfile now pins modern Jekyll +
|
|
803
|
+
`jekyll-remote-theme` + `webrick`, and both the Gemfile and the remote
|
|
804
|
+
`_config.yml` template add `jekyll-include-cache` (required by the theme's
|
|
805
|
+
layouts).
|
|
806
|
+
|
|
8
807
|
## [1.27.0](https://github.com/bamr87/zer0-mistakes/compare/v1.26.0...v1.27.0) (2026-07-22)
|
|
9
808
|
|
|
10
809
|
|
|
@@ -34,7 +833,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
34
833
|
|
|
35
834
|
* **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))
|
|
36
835
|
|
|
37
|
-
##
|
|
836
|
+
## Detailed notes — v1.27.0
|
|
38
837
|
|
|
39
838
|
### Added
|
|
40
839
|
|
|
@@ -140,7 +939,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
140
939
|
- **Author avatars never render as protocol-relative `//assets/…` URLs** —
|
|
141
940
|
`author-avatar-url.html` now builds the relative-path branch in a capture,
|
|
142
941
|
collapses doubled slashes, and applies `relative_url` exactly once, instead
|
|
143
|
-
of the manual `{{ site.baseurl }}/{{ site.public_folder }}{{ avatar }}`
|
|
942
|
+
of the manual `{% raw %}{{ site.baseurl }}/{{ site.public_folder }}{{ avatar }}{% endraw %}`
|
|
144
943
|
concatenation that produced `src="//assets/…"` (a URL browsers resolve
|
|
145
944
|
against a host named `assets`) on consumer sites where `public_folder` is
|
|
146
945
|
unset or carries a leading slash
|
|
@@ -222,7 +1021,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
222
1021
|
* **navigation:** remove redundant entries from navigation menus ([916eca2](https://github.com/bamr87/zer0-mistakes/commit/916eca269726c984c5c0c9dc9533c83d9975f906))
|
|
223
1022
|
* **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))
|
|
224
1023
|
|
|
225
|
-
##
|
|
1024
|
+
## Detailed notes — v1.25.0
|
|
226
1025
|
|
|
227
1026
|
### Changed
|
|
228
1027
|
|
|
@@ -332,7 +1131,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
332
1131
|
* **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))
|
|
333
1132
|
* **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)
|
|
334
1133
|
|
|
335
|
-
##
|
|
1134
|
+
## Detailed notes — v1.24.0–v1.25.0
|
|
336
1135
|
|
|
337
1136
|
### Bug Fixes
|
|
338
1137
|
|
|
@@ -423,7 +1222,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
423
1222
|
|
|
424
1223
|
* 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))
|
|
425
1224
|
|
|
426
|
-
##
|
|
1225
|
+
## Detailed notes — v1.24.0
|
|
427
1226
|
|
|
428
1227
|
### Added
|
|
429
1228
|
- **Visual-evidence standard + reusable evidence kit.** UI/behavioural changes
|
|
@@ -686,7 +1485,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
686
1485
|
to it from the Bootstrap, Layouts, and Styles docs.
|
|
687
1486
|
- **Bylines now use the shared author component.** The `article`, `note`,
|
|
688
1487
|
`notebook`, `news`, and `section` layouts plus `components/post-card.html`
|
|
689
|
-
previously printed `{{ page.author }}` as bare text; they now render
|
|
1488
|
+
previously printed `{% raw %}{{ page.author }}{% endraw %}` as bare text; they now render
|
|
690
1489
|
`components/author-card.html` (`inline`), so a known author key resolves to a
|
|
691
1490
|
display name, avatar, and a link to their profile page. The inline
|
|
692
1491
|
"About the Author" block that was hard-coded in `_layouts/article.html` was
|
|
@@ -833,7 +1632,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
833
1632
|
- Version bump: patch release
|
|
834
1633
|
|
|
835
1634
|
### Commits in this release
|
|
836
|
-
- ae76a61f fix(content-review): correct code-fence detection (closing fences + {% raw %}) (#155)
|
|
1635
|
+
- ae76a61f fix(content-review): correct code-fence detection (closing fences + {% raw %}{% raw %}{% endraw %}) (#155)
|
|
837
1636
|
- f00fb654 docs(seo): strengthen SEO docs index metadata + fix agent-tier workflow (#154)
|
|
838
1637
|
|
|
839
1638
|
### Fixed
|
|
@@ -843,10 +1642,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
843
1642
|
a file's score (e.g. `pages/_about/features/jekyll.md` scored 0/100 almost
|
|
844
1643
|
entirely from this false positive). The check now tracks fence open/close state
|
|
845
1644
|
and only validates opening fences.
|
|
846
|
-
- **content-review: ignore Liquid `{% raw %}` blocks** in the quality and style
|
|
847
|
-
checks. Code fences, headings, images, and terminology inside
|
|
848
|
-
{% endraw %}` are literal display examples, not page
|
|
849
|
-
counted as real findings.
|
|
1645
|
+
- **content-review: ignore Liquid `{% raw %}{% raw %}{% endraw %}` blocks** in the quality and style
|
|
1646
|
+
checks. Code fences, headings, images, and terminology inside a Liquid
|
|
1647
|
+
`{% raw %}{% raw %}{% endraw %}` block are literal display examples, not page
|
|
1648
|
+
structure, and were being counted as real findings.
|
|
850
1649
|
|
|
851
1650
|
## [1.18.0] - 2026-06-13
|
|
852
1651
|
|
|
@@ -1274,7 +2073,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1274
2073
|
- **Sidebar collapse — VS Code style**: Left sidebar (`#bdSidebar`) and right TOC (`#tocContents`) now collapse to a slim 36 px rail (`--zer0-sidebar-rail-width`) instead of being fully hidden on desktop. The visibility toggle icon (`bi-layout-sidebar-inset` / `bi-layout-sidebar-inset-reverse`) stays mounted on the rail so users can re-expand the panel with a single click — the floating action buttons (`.bd-sidebar-fab`, `.bd-toc-fab`) are now hidden at `≥992 px` since the rail toggle replaces them. `_sass/core/_docs-layout.scss`, `_sass/layouts/_navbar-extras.scss`.
|
|
1275
2074
|
- **Smooth transitions**: `.bd-layout` and `.bd-main` now animate `grid-template-columns` and `gap` over `--zer0-motion-duration-base` (0.3 s) with `--zer0-motion-ease-standard`; sidebar contents cross-fade via `opacity` + delayed `visibility`. Honors `@media (prefers-reduced-motion: reduce)` by disabling all related transitions.
|
|
1276
2075
|
- **Toggle behavior**: `sidebar-visibility.js` and `toc-visibility.js` no longer set `button.hidden = true` on the rail toggle when collapsed, keeping it interactive in the collapsed state. Aria labels (`Hide…` / `Show…`) update on each toggle.
|
|
1277
|
-
- **Cache-bust**: Added
|
|
2076
|
+
- **Cache-bust**: Added `{% raw %}?v={{ site.time | date: '%s' }}{% endraw %}` to the navigation ES-module `<script type="module">` tag in `_includes/components/js-cdn.html` to force re-fetch on rebuild (browsers cache ES modules indefinitely by URL).
|
|
1278
2077
|
- **Navbar dropdown**: Dropdown toggle button set to `align-self: stretch` so it spans the full navbar height, making it easier to invoke on touch/small screens; chevron icon `font-size` increased to `1em` for better legibility. `_sass/core/_navbar.scss`.
|
|
1279
2078
|
- **Syntax highlighting**: Dual-palette system — `_sass/core/_syntax.scss` now uses a GitHub Light palette for `.highlight` (light mode) and scopes the Material Dark base16 palette to `[data-bs-theme="dark"] .highlight`, fixing near-invisible token colors on light backgrounds.
|
|
1280
2079
|
- **Theme preview gallery**: Expanded to 20 sections with 6 new components: Callouts (5 types), Accordion, Progress & Spinners, Breadcrumb & Pagination, Tooltips & Popovers, and Icons showcase. TOC updated accordingly; Bootstrap tooltip/popover JS initializer added. `_includes/components/theme-preview-gallery.html`, `pages/_about/settings/theme-preview.md`.
|
|
@@ -2319,7 +3118,7 @@ See [`docs/installation/migration-from-0.x.md`](docs/installation/migration-from
|
|
|
2319
3118
|
- **Troubleshooting Guide**: Added sections for Docker issues, Jekyll build errors, front matter problems, performance optimization
|
|
2320
3119
|
- **Jekyll Guide**: Added directory structure, configuration files, content collections, essential commands, topic index
|
|
2321
3120
|
- **Bootstrap Guide**: Added CDN loading patterns, key components, responsive breakpoints, custom styles, icons
|
|
2322
|
-
- **Liquid Guide**: Added syntax examples with `{% raw %}` tags, filters, control flow, includes
|
|
3121
|
+
- **Liquid Guide**: Added syntax examples with `{% raw %}{% raw %}{% endraw %}` tags, filters, control flow, includes
|
|
2323
3122
|
- **Ruby Guide**: Added version commands, common commands, key files, Docker usage, troubleshooting
|
|
2324
3123
|
- **Front Matter Guide**: Added required/optional fields, layout options, collection-specific fields, complete examples
|
|
2325
3124
|
- All documentation pages now include `sidebar: nav: docs` for consistent navigation
|