jekyll-theme-zer0 1.13.1 → 1.15.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 +38 -0
- data/README.md +25 -23
- data/_data/backlog.yml +67 -15
- data/_data/roadmap.yml +29 -17
- data/_includes/components/js-cdn.html +3 -0
- data/_includes/content/intro.html +13 -3
- data/_layouts/note.html +12 -3
- data/assets/js/palette-generator.js +1 -1
- data/assets/js/share-actions.js +156 -0
- data/assets/js/theme-customizer.js +3 -1
- data/scripts/bin/validate +1 -0
- data/scripts/test/lib/run_tests.sh +1 -0
- data/scripts/test/lib/test_locale_independence.sh +29 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6bd5748efd683917f588e3f0e130536a6ba00727f0d2027445261b1258d2b22d
|
|
4
|
+
data.tar.gz: dcd71edd2118b837980feccce2474ab6936d7838756d4ed3a9aa4a80ef76ff75
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28d42c8f1d75356b055eeeb493d8daf466ef1e8d23eb8aade96f4c77de0f1b1b7d307f821b5ef65716d2379920bd68f9d4862d0ad0fc214b82f9398349041617
|
|
7
|
+
data.tar.gz: 5c2d7da877cdcaa317ef6e90e6c60e5f28098dd1742101c793140801a45d8aa029f8d97960d830bdd4ef00c22f4241f4c2fd9c2e2659c218d2ae69369fd80f9a
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ 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
|
+
## [1.15.0] - 2026-06-12
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Version bump: minor release
|
|
12
|
+
|
|
13
|
+
### Commits in this release
|
|
14
|
+
- 85d0295a feat(quality): implement six backlog tasks — T-003/004/008/014/015/016 (#144)
|
|
15
|
+
- 71b8fe46 fix(gemspec): require Ruby >= 3.2 to match modern dependency floor (#93)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **Contribution templates (T-003)**: bug-report and feature-request issue forms, contact links, and a PR template with the conventional-commit/CHANGELOG/test checklist
|
|
19
|
+
- **Locale-independence guard (T-015)**: lib test suite runs the roadmap/backlog/preflight validators under `LC_ALL=C LANG=C` so the UTF-8 crash class fixed in 1.12.1 cannot return
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **Theme customizer (T-008)**: YAML export now quotes hex color values in both builders — unquoted `#RRGGBB` parsed as a YAML comment and silently dropped colors; frozen regression test promoted to live
|
|
23
|
+
- **Docs lint baseline (T-004/T-014)**: ~1,600 markdownlint violations fixed or config-tuned to zero (MD060 disabled as post-config stylistic noise, MD025 front-matter handling, MD024 siblings-only); a stray code fence that swallowed the troubleshooting "Advanced Topics" section into a code block repaired; table pipes escaped; 15 dead README links remapped to the reorganized `docs/` tree
|
|
24
|
+
- **site_generation suite (T-016)**: `jekyll build` failures now fail the suite instead of degrading to warnings (missing-bundler skip retained)
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **Docs lint gate (T-014)**: both `|| true` suppressions removed from `docs-validate.yml` — markdownlint now blocks on a zero-violation baseline
|
|
28
|
+
|
|
29
|
+
## [1.14.0] - 2026-06-11
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- Version bump: minor release
|
|
33
|
+
|
|
34
|
+
### Commits in this release
|
|
35
|
+
- 5de341aa feat(security): sanitize sensitive config lines in admin config-page DOM (T-009) (#140)
|
|
36
|
+
- 42468785 chore(deps): update Ruby gem dependencies (#129)
|
|
37
|
+
- 89e21988 Improve LinkedIn share flow with cleaned article summary (#99)
|
|
38
|
+
|
|
39
|
+
### Security
|
|
40
|
+
- **Admin config page (T-009 hardening)**: added a pure-Liquid line-redaction layer for the hidden `<pre id="cfg-full-yaml">` element — the `sanitize_config_yaml` plugin filter shipped in 1.13.1 does not run on GitHub Pages builds (safe mode ignores custom plugins, and the unknown filter is a silent no-op), so Pages-built sites were still injecting raw config; the Liquid layer protects every build path, with the plugin filter kept as defense-in-depth
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
- **Workflow lint (T-017)**: `version-bump.yml` now passes the repo yamllint config (trailing spaces, bracket spacing, sequence indentation) — these pre-existing violations failed the `auto-version` integration suite on every code PR once the T-012 gate went live; YAML verified semantically identical before/after
|
|
44
|
+
- **Changelog tooling**: `update_changelog_file` normalizes trailing newlines on the entry, guaranteeing exactly one blank line before the next release block even when callers pass entries via command substitution (review feedback on the T-012 PR)
|
|
45
|
+
|
|
8
46
|
## [1.13.1] - 2026-06-11
|
|
9
47
|
|
|
10
48
|
### Changed
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: zer0-mistakes
|
|
3
3
|
sub-title: AI-Native Jekyll Theme
|
|
4
4
|
description: AI-native Jekyll theme for GitHub Pages — Docker-first development, AI-powered installation, multi-agent integration (Copilot, Codex, Cursor, Claude), AI preview-image generation, and AIEO content optimization with Bootstrap 5.3.
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.15.0
|
|
6
6
|
layout: landing
|
|
7
7
|
tags:
|
|
8
8
|
- jekyll
|
|
@@ -20,7 +20,7 @@ categories:
|
|
|
20
20
|
- bootstrap
|
|
21
21
|
- ai-tooling
|
|
22
22
|
created: 2024-02-10T23:51:11.480Z
|
|
23
|
-
lastmod: 2026-06-
|
|
23
|
+
lastmod: 2026-06-12T01:01:59.000Z
|
|
24
24
|
draft: false
|
|
25
25
|
permalink: /
|
|
26
26
|
slug: zer0
|
|
@@ -571,7 +571,7 @@ cd <your-username>.github.io
|
|
|
571
571
|
docker-compose up
|
|
572
572
|
```
|
|
573
573
|
|
|
574
|
-
See [docs/FORKING.md](docs/
|
|
574
|
+
See [docs/FORKING.md](docs/installation/forking.md) for the full progressive workflow.
|
|
575
575
|
|
|
576
576
|
---
|
|
577
577
|
|
|
@@ -703,7 +703,7 @@ zer0-mistakes documentation is split across three audiences. Pick the layer that
|
|
|
703
703
|
| [📊 Analytics](https://zer0-mistakes.com/docs/analytics/) | PostHog, Google Analytics setup |
|
|
704
704
|
| [🔍 SEO](https://zer0-mistakes.com/docs/seo/) | Meta tags, sitemap, structured data |
|
|
705
705
|
| [📓 Jupyter Notebooks](https://github.com/bamr87/zer0-mistakes/blob/main/docs/JUPYTER_NOTEBOOKS.md) | Notebook conversion documentation |
|
|
706
|
-
| [📝 PRD](docs/
|
|
706
|
+
| [📝 PRD](docs/architecture/prd-requirements.md) | Product requirements & roadmap |
|
|
707
707
|
| [🔒 Privacy Policy](https://zer0-mistakes.com/privacy-policy/) | GDPR/CCPA compliant privacy docs |
|
|
708
708
|
|
|
709
709
|
### Contributor Technical Reference
|
|
@@ -712,18 +712,18 @@ These files live in the repo under `docs/` and are intended for theme contributo
|
|
|
712
712
|
|
|
713
713
|
| File | Topic |
|
|
714
714
|
|------|-------|
|
|
715
|
-
| [docs/design-system.md](docs/design-system.md) | Design system overview |
|
|
716
|
-
| [docs/design-tokens.md](docs/design-tokens.md) | Design tokens reference |
|
|
717
|
-
| [docs/components.md](docs/components.md) | UI component catalogue |
|
|
718
|
-
| [docs/layouts-and-navigation.md](docs/layouts-and-navigation.md) | Layout hierarchy & navigation |
|
|
719
|
-
| [docs/theming.md](docs/theming.md) | Sass / Bootstrap theming guide |
|
|
720
|
-
| [docs/customization.md](docs/customization.md) | Site customization patterns |
|
|
721
|
-
| [docs/configuration.md](docs/configuration.md) | `_config.yml` reference |
|
|
722
|
-
| [docs/code-blocks.md](docs/code-blocks.md) | Syntax highlighting setup |
|
|
723
|
-
| [docs/extending.md](docs/extending.md) | Adding layouts, includes & plugins |
|
|
724
|
-
| [docs/js-api.md](docs/js-api.md) | JavaScript module API |
|
|
725
|
-
| [docs/TROUBLESHOOTING.md](docs/
|
|
726
|
-
| [docs/FORKING.md](docs/
|
|
715
|
+
| [docs/design-system.md](docs/ui/design-system.md) | Design system overview |
|
|
716
|
+
| [docs/design-tokens.md](docs/ui/design-tokens.md) | Design tokens reference |
|
|
717
|
+
| [docs/components.md](docs/ui/components.md) | UI component catalogue |
|
|
718
|
+
| [docs/layouts-and-navigation.md](docs/ui/layouts-and-navigation.md) | Layout hierarchy & navigation |
|
|
719
|
+
| [docs/theming.md](docs/ui/theming.md) | Sass / Bootstrap theming guide |
|
|
720
|
+
| [docs/customization.md](docs/ui/customization.md) | Site customization patterns |
|
|
721
|
+
| [docs/configuration.md](docs/ui/configuration.md) | `_config.yml` reference |
|
|
722
|
+
| [docs/code-blocks.md](docs/ui/code-blocks.md) | Syntax highlighting setup |
|
|
723
|
+
| [docs/extending.md](docs/ui/extending.md) | Adding layouts, includes & plugins |
|
|
724
|
+
| [docs/js-api.md](docs/ui/js-api.md) | JavaScript module API |
|
|
725
|
+
| [docs/TROUBLESHOOTING.md](docs/development/troubleshooting.md) | Common issues & fixes |
|
|
726
|
+
| [docs/FORKING.md](docs/installation/forking.md) | Forking & personalization guide |
|
|
727
727
|
|
|
728
728
|
---
|
|
729
729
|
|
|
@@ -803,7 +803,7 @@ When you fork the theme as a starter, the workflows come with you. To make them
|
|
|
803
803
|
|
|
804
804
|
## 🗺 Roadmap
|
|
805
805
|
|
|
806
|
-
The diagram and table below are auto-generated from [`_data/roadmap.yml`](_data/roadmap.yml) by [`scripts/generate-roadmap.sh`](scripts/generate-roadmap.sh). See the full [Roadmap page](https://zer0-mistakes.com/roadmap/) for per-version detail and the [PRD](docs/
|
|
806
|
+
The diagram and table below are auto-generated from [`_data/roadmap.yml`](_data/roadmap.yml) by [`scripts/generate-roadmap.sh`](scripts/generate-roadmap.sh). See the full [Roadmap page](https://zer0-mistakes.com/roadmap/) for per-version detail and the [PRD](docs/architecture/prd-requirements.md) for product context.
|
|
807
807
|
|
|
808
808
|
<!-- ROADMAP_MERMAID:START -->
|
|
809
809
|
|
|
@@ -830,10 +830,11 @@ gantt
|
|
|
830
830
|
v1.9 Installer v2 & Site Scraper :done, 2026-05, 2026-05
|
|
831
831
|
v1.10 Roadmap Validation :done, 2026-06, 2026-06
|
|
832
832
|
v1.11 Continuous-Evolution Loop :done, 2026-06, 2026-06
|
|
833
|
+
v1.12 Headless Endpoints :done, 2026-06, 2026-06
|
|
834
|
+
v1.13 Quality Framework — First Wave :done, 2026-06, 2026-06
|
|
833
835
|
section Current
|
|
834
|
-
v1.
|
|
836
|
+
v1.14 Zer0-Mistake Quality Framework :active, 2026-06, 2026-08
|
|
835
837
|
section Future
|
|
836
|
-
v1.13 Zer0-Mistake Quality Framework :2026-06, 2026-08
|
|
837
838
|
v2.0 CMS Integration :2026-06, 2026-08
|
|
838
839
|
v2.1 i18n Support :2026-08, 2026-10
|
|
839
840
|
v2.2 Advanced Analytics :2026-10, 2026-12
|
|
@@ -864,8 +865,9 @@ gantt
|
|
|
864
865
|
| **v1.9** | ✅ Completed | May 2026 | Modular installer v2 with deploy plugins, AI wizard pipeline, and a site scraper. |
|
|
865
866
|
| **v1.10** | ✅ Completed | Jun 2026 | Roadmap integrity validation and catch-up milestones so the roadmap tracks the shipped gem. |
|
|
866
867
|
| **v1.11** | ✅ Completed | Jun 2026 | Self-sustaining backlog loop so AI agents keep improving the repo between human sessions. |
|
|
867
|
-
| **v1.12** |
|
|
868
|
-
| **v1.13** |
|
|
868
|
+
| **v1.12** | ✅ Completed | Jun 2026 | Machine-readable site endpoints for downstream sites and AI agents. |
|
|
869
|
+
| **v1.13** | ✅ Completed | Jun 2026 | First shipped wave of the Zer0-Mistake Quality Framework: CI gate parity and DOM sanitization. |
|
|
870
|
+
| **v1.14** | 🚧 In Progress | Current (1.14.x) | Close the gap between the repo's quality gates and what CI actually enforces — no mistake lands green. |
|
|
869
871
|
| **v2.0** | 🗓 Planned | Q3 2026 | Headless CMS integration with a content API and admin dashboard. |
|
|
870
872
|
| **v2.1** | 🗓 Planned | Q4 2026 | Multi-language content support with locale-aware routing. |
|
|
871
873
|
| **v2.2** | 🗓 Planned | Q4 2026 | Visual theme customizer, A/B testing, and conversion funnels. |
|
|
@@ -909,7 +911,7 @@ git push origin feature/awesome-feature
|
|
|
909
911
|
|
|
910
912
|
| Metric | Value |
|
|
911
913
|
|--------|-------|
|
|
912
|
-
| **Current Version** | 1.
|
|
914
|
+
| **Current Version** | 1.15.0 ([RubyGems](https://rubygems.org/gems/jekyll-theme-zer0), [CHANGELOG](/CHANGELOG)) |
|
|
913
915
|
| **Documented Features** | 43 ([Feature Registry](https://github.com/bamr87/zer0-mistakes/blob/main/_data/features.yml)) |
|
|
914
916
|
| **Setup Time** | 2-5 minutes ([install.sh benchmarks](https://github.com/bamr87/zer0-mistakes/blob/main/install.sh)) |
|
|
915
917
|
| **Documentation Pages** | 70+ ([browse docs](https://zer0-mistakes.com/pages/)) |
|
|
@@ -964,6 +966,6 @@ And these AI partners that make zer0-mistakes truly AI-native:
|
|
|
964
966
|
|
|
965
967
|
**Built with ❤️ — and a little help from our AI partners — for the Jekyll community**
|
|
966
968
|
|
|
967
|
-
**v1.
|
|
969
|
+
**v1.15.0** • [Changelog](CHANGELOG.md) • [License](LICENSE) • [Contributing](CONTRIBUTING.md) • [AI Agent Guide](AGENTS.md)
|
|
968
970
|
|
|
969
971
|
|
data/_data/backlog.yml
CHANGED
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
|
|
56
56
|
meta:
|
|
57
57
|
title: "zer0-mistakes Backlog"
|
|
58
|
-
updated: 2026-06-
|
|
59
|
-
next_id:
|
|
58
|
+
updated: 2026-06-12
|
|
59
|
+
next_id: 19
|
|
60
60
|
|
|
61
61
|
tasks:
|
|
62
62
|
# --- Housekeeping (seeded so the loop has work on day one) ------------------
|
|
@@ -106,7 +106,7 @@ tasks:
|
|
|
106
106
|
|
|
107
107
|
- id: T-003
|
|
108
108
|
title: "Add GitHub issue templates and a pull-request template"
|
|
109
|
-
status:
|
|
109
|
+
status: done
|
|
110
110
|
priority: P2
|
|
111
111
|
area: infra
|
|
112
112
|
risk: standard
|
|
@@ -116,17 +116,21 @@ tasks:
|
|
|
116
116
|
The repo has no `.github/ISSUE_TEMPLATE/` or PR template. Add a bug-report
|
|
117
117
|
and feature-request issue form plus a PR template that nudges contributors
|
|
118
118
|
toward conventional commits, CHANGELOG updates, and the test checklist.
|
|
119
|
+
Done 2026-06-12: bug-report and feature-request issue forms, config.yml
|
|
120
|
+
with contact links (blank issues stay enabled for the API-driven backlog
|
|
121
|
+
sync), and a PR template with the conventional-commit/CHANGELOG/test
|
|
122
|
+
checklist.
|
|
119
123
|
acceptance:
|
|
120
124
|
- "`.github/ISSUE_TEMPLATE/bug_report.yml` and `feature_request.yml` exist and render."
|
|
121
125
|
- "`.github/pull_request_template.md` exists with a conventional-commit + CHANGELOG + tests checklist."
|
|
122
126
|
- "Agent-filed backlog issues remain compatible with the new templates (no broken automation)."
|
|
123
127
|
links: { issue: null, pr: null, roadmap: null }
|
|
124
128
|
created: 2026-05-31
|
|
125
|
-
updated: 2026-
|
|
129
|
+
updated: 2026-06-12
|
|
126
130
|
|
|
127
131
|
- id: T-004
|
|
128
132
|
title: "Docs-freshness sweep: reconcile docs/ ↔ pages/_docs/ and fix broken links"
|
|
129
|
-
status:
|
|
133
|
+
status: done
|
|
130
134
|
priority: P2
|
|
131
135
|
area: docs
|
|
132
136
|
risk: low
|
|
@@ -136,13 +140,18 @@ tasks:
|
|
|
136
140
|
Run the markdown-link checker and audit the two-tier docs for drift,
|
|
137
141
|
stale dates/versions, and any user/technical pages that fell out of sync
|
|
138
142
|
after the recent alignment commit.
|
|
143
|
+
Done 2026-06-12: markdownlint baseline cleaned to zero violations
|
|
144
|
+
(~1,600 fixed: auto-fix pass, MD060/MD025/MD024 config tuning, fence
|
|
145
|
+
languages, table pipe escapes, a stray fence swallowing a docs section),
|
|
146
|
+
15 dead README links remapped to the reorganized docs/ tree,
|
|
147
|
+
check-links.sh reports 0 broken links.
|
|
139
148
|
acceptance:
|
|
140
149
|
- "`markdown-link-check` (config in `.github/config/`) reports no broken internal links."
|
|
141
150
|
- "Any stale version/date references in `docs/` and `pages/_docs/` are corrected."
|
|
142
151
|
- "Cross-links between the user tier and technical tier resolve both ways."
|
|
143
152
|
links: { issue: null, pr: null, roadmap: null }
|
|
144
153
|
created: 2026-05-31
|
|
145
|
-
updated: 2026-
|
|
154
|
+
updated: 2026-06-12
|
|
146
155
|
|
|
147
156
|
- id: T-005
|
|
148
157
|
title: "Coverage baseline: identify the lowest-covered subsystems toward the 90% goal"
|
|
@@ -192,7 +201,7 @@ tasks:
|
|
|
192
201
|
|
|
193
202
|
- id: T-008
|
|
194
203
|
title: "Fix theme-customizer YAML export to quote hex color values"
|
|
195
|
-
status:
|
|
204
|
+
status: done
|
|
196
205
|
priority: P2
|
|
197
206
|
area: feat
|
|
198
207
|
risk: standard
|
|
@@ -203,13 +212,17 @@ tasks:
|
|
|
203
212
|
YAML without quoting strings that start with `#`. Unquoted `#RRGGBB` is treated as a
|
|
204
213
|
YAML comment by parsers, silently dropping colour values. A regression guard in
|
|
205
214
|
`test/visual/theme-colors.spec.js` is frozen as `test.fixme` until the bug is fixed.
|
|
215
|
+
Done 2026-06-12: both YAML builders (theme-customizer.js fallback and
|
|
216
|
+
palette-generator.js commented overrides) quote color values; frozen
|
|
217
|
+
regression test promoted to live test(); export verified parseable by
|
|
218
|
+
Ruby YAML with colors preserved.
|
|
206
219
|
acceptance:
|
|
207
220
|
- "JS export wraps every hex colour value (matching `/#[0-9a-fA-F]{3,8}/`) in double quotes in the generated YAML."
|
|
208
221
|
- "The `test.fixme` in `test/visual/theme-colors.spec.js` is promoted to a live `test()` and passes in CI."
|
|
209
222
|
- "Exported YAML is valid when parsed by `yaml.safe_load` in Ruby."
|
|
210
223
|
links: { issue: null, pr: null, roadmap: null }
|
|
211
224
|
created: 2026-06-01
|
|
212
|
-
updated: 2026-06-
|
|
225
|
+
updated: 2026-06-12
|
|
213
226
|
|
|
214
227
|
- id: T-009
|
|
215
228
|
title: "Sanitize sensitive config keys from admin config-page DOM injection"
|
|
@@ -225,6 +238,9 @@ tasks:
|
|
|
225
238
|
(`api_key`, `token`, PostHog `phc_*` keys, etc.) they are exposed in the page
|
|
226
239
|
DOM. A regression test in `test/visual/security.spec.js` is frozen as
|
|
227
240
|
`test.fixme` until a sanitisation pass is in place.
|
|
241
|
+
Done 2026-06-11: pure-Liquid line filter redacts matching lines before
|
|
242
|
+
DOM injection (GitHub Pages safe — no custom plugin); regression test
|
|
243
|
+
promoted to a live `test()`; visible Raw-YAML tab untouched.
|
|
228
244
|
acceptance:
|
|
229
245
|
- "The Liquid/Ruby that populates `<pre id=\"cfg-full-yaml\">` strips or masks keys matching `api_key`, `secret`, `password`, `token`, and `phc_` prefix before DOM injection."
|
|
230
246
|
- "The `test.fixme` in `test/visual/security.spec.js` is promoted to a live `test()` and passes in CI."
|
|
@@ -339,7 +355,7 @@ tasks:
|
|
|
339
355
|
|
|
340
356
|
- id: T-014
|
|
341
357
|
title: "Re-arm the docs link-check gate (remove warn-only || true)"
|
|
342
|
-
status:
|
|
358
|
+
status: done
|
|
343
359
|
priority: P2
|
|
344
360
|
area: lint
|
|
345
361
|
risk: standard
|
|
@@ -349,17 +365,20 @@ tasks:
|
|
|
349
365
|
`docs-validate.yml` runs markdown-link-check with `|| true` ("warn-only
|
|
350
366
|
until baseline is clean"), so broken links accumulate. Fix the links it
|
|
351
367
|
currently reports, then drop the `|| true` so the gate blocks.
|
|
368
|
+
Done 2026-06-12: baseline cleaned to zero violations and both
|
|
369
|
+
warn-only suppressions removed from docs-validate.yml — the lint gate
|
|
370
|
+
now blocks. (The internal link check was already blocking.)
|
|
352
371
|
acceptance:
|
|
353
372
|
- "All links reported by the current `docs-validate.yml` run are fixed or allowlisted in `.github/config/.markdown-link-check.json`."
|
|
354
373
|
- "Both `|| true` suppressions removed from `docs-validate.yml`."
|
|
355
374
|
- "`docs-validate.yml` passes blocking on a follow-up PR."
|
|
356
375
|
links: { issue: null, pr: null, roadmap: "1.13" }
|
|
357
376
|
created: 2026-06-10
|
|
358
|
-
updated: 2026-06-
|
|
377
|
+
updated: 2026-06-12
|
|
359
378
|
|
|
360
379
|
- id: T-015
|
|
361
380
|
title: "Locale-independence regression guard for Ruby/Bash tooling"
|
|
362
|
-
status:
|
|
381
|
+
status: done
|
|
363
382
|
priority: P2
|
|
364
383
|
area: infra
|
|
365
384
|
risk: standard
|
|
@@ -371,17 +390,21 @@ tasks:
|
|
|
371
390
|
only reproduced without a UTF-8 locale. Add a guard so the bug class
|
|
372
391
|
cannot return: run the validators under `LC_ALL=C` in a lib test or a
|
|
373
392
|
dedicated CI step.
|
|
393
|
+
Done 2026-06-12: scripts/test/lib/test_locale_independence.sh runs
|
|
394
|
+
generate-roadmap --check/--validate, sync-backlog --check, and
|
|
395
|
+
validate --quick under LC_ALL=C LANG=C; verified the guard fails when
|
|
396
|
+
the explicit-UTF-8 read is reverted.
|
|
374
397
|
acceptance:
|
|
375
398
|
- "A test (scripts/test/lib/) or CI step runs `generate-roadmap.rb --check`, `sync-backlog.rb --check`, and `validate --quick` with `LC_ALL=C LANG=C`."
|
|
376
399
|
- "The guard fails when the explicit-UTF-8 reads are reverted (verified once locally)."
|
|
377
400
|
- "`./scripts/bin/test` stays green."
|
|
378
401
|
links: { issue: null, pr: null, roadmap: "1.13" }
|
|
379
402
|
created: 2026-06-10
|
|
380
|
-
updated: 2026-06-
|
|
403
|
+
updated: 2026-06-12
|
|
381
404
|
|
|
382
405
|
- id: T-016
|
|
383
406
|
title: "site_generation suite: fail on Jekyll build errors instead of warning"
|
|
384
|
-
status:
|
|
407
|
+
status: done
|
|
385
408
|
priority: P2
|
|
386
409
|
area: tests
|
|
387
410
|
risk: standard
|
|
@@ -395,17 +418,20 @@ tasks:
|
|
|
395
418
|
the suite now gating PRs in CI (working bundler guaranteed), build
|
|
396
419
|
failures should fail the suite; keep the skip only for genuinely
|
|
397
420
|
missing toolchain (no bundler).
|
|
421
|
+
Done 2026-06-12: jekyll build failures now fail the suite (bundler-
|
|
422
|
+
missing still skips); verified strict suite passes locally with real
|
|
423
|
+
builds.
|
|
398
424
|
acceptance:
|
|
399
425
|
- "A non-zero `jekyll build` exit fails the suite when bundler is available."
|
|
400
426
|
- "The bundler-missing path still skips with a warning (local minimal environments)."
|
|
401
427
|
- "Suite passes in CI and via `./test/test_runner.sh --suites site_generation` locally."
|
|
402
428
|
links: { issue: null, pr: null, roadmap: "1.13" }
|
|
403
429
|
created: 2026-06-10
|
|
404
|
-
updated: 2026-06-
|
|
430
|
+
updated: 2026-06-12
|
|
405
431
|
|
|
406
432
|
- id: T-017
|
|
407
433
|
title: "Fix yamllint violations in .github/workflows/version-bump.yml"
|
|
408
|
-
status:
|
|
434
|
+
status: done
|
|
409
435
|
priority: P2
|
|
410
436
|
area: lint
|
|
411
437
|
risk: low
|
|
@@ -417,6 +443,9 @@ tasks:
|
|
|
417
443
|
integration test (which runs yamllint) to fail in CI on every PR. Discovered
|
|
418
444
|
while babysitting PR #141 — the file was unchanged by that PR, confirming
|
|
419
445
|
the failures are pre-existing.
|
|
446
|
+
Done 2026-06-11: full cleanup (trailing spaces, brackets, sequence
|
|
447
|
+
indentation) landed with the T-009 PR; YAML verified semantically
|
|
448
|
+
identical and yamllint exits 0 with the repo config.
|
|
420
449
|
acceptance:
|
|
421
450
|
- "`yamllint -c .github/config/.yamllint.yml .github/workflows/version-bump.yml` exits 0."
|
|
422
451
|
- "`./scripts/test/integration/auto-version` passes the 'version-bump workflow syntax' check."
|
|
@@ -425,3 +454,26 @@ tasks:
|
|
|
425
454
|
created: 2026-06-11
|
|
426
455
|
updated: 2026-06-11
|
|
427
456
|
|
|
457
|
+
- id: T-018
|
|
458
|
+
title: "Admin config page displays a stale copy of _config.yml — keep it in sync safely"
|
|
459
|
+
status: open
|
|
460
|
+
priority: P2
|
|
461
|
+
area: feat
|
|
462
|
+
risk: standard
|
|
463
|
+
effort: M
|
|
464
|
+
source: audit
|
|
465
|
+
summary: >-
|
|
466
|
+
`pages/_about/settings/config.md` renders `pages/_about/settings/_config.yml`
|
|
467
|
+
via `include_relative` (Liquid cannot reach the repo root), and that copy
|
|
468
|
+
has drifted from the live `_config.yml` (it predates, e.g., the PostHog
|
|
469
|
+
analytics block). Found while implementing T-009. Caution: a naive
|
|
470
|
+
refresh would inject the live `phc_` api_key into the *visible* Raw-YAML
|
|
471
|
+
tab — any sync mechanism must sanitize the visible tab the same way
|
|
472
|
+
T-009 sanitizes the hidden copy element, or redact at sync time.
|
|
473
|
+
acceptance:
|
|
474
|
+
- "The config shown at /about/config/ matches the live `_config.yml` (automated sync step or build-time check that fails on drift)."
|
|
475
|
+
- "The visible Raw-YAML tab applies the same sensitive-line redaction as the hidden `cfg-full-yaml` element."
|
|
476
|
+
- "`test/visual/security.spec.js` raw-tab test passes without its silent skip path (locator matches the actual `code#cfg-raw-yaml` element)."
|
|
477
|
+
links: { issue: null, pr: null, roadmap: "1.13" }
|
|
478
|
+
created: 2026-06-11
|
|
479
|
+
updated: 2026-06-11
|
data/_data/roadmap.yml
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
meta:
|
|
61
61
|
title: "zer0-mistakes Roadmap"
|
|
62
62
|
tagline: "Past releases, current focus, and future plans for the zer0-mistakes Jekyll theme."
|
|
63
|
-
updated: 2026-06-
|
|
63
|
+
updated: 2026-06-12
|
|
64
64
|
|
|
65
65
|
milestones:
|
|
66
66
|
# --- Completed -------------------------------------------------------------
|
|
@@ -313,38 +313,50 @@ milestones:
|
|
|
313
313
|
- "`/repo-audit` and `/backlog-implement` agent routines"
|
|
314
314
|
- "Documentation maintenance system and consolidation"
|
|
315
315
|
|
|
316
|
-
# --- Current ---------------------------------------------------------------
|
|
317
|
-
|
|
318
316
|
- version: "1.12"
|
|
319
317
|
title: "Headless Endpoints"
|
|
320
|
-
status:
|
|
321
|
-
section:
|
|
318
|
+
status: completed
|
|
319
|
+
section: Completed
|
|
322
320
|
start: 2026-06
|
|
323
321
|
end: 2026-06
|
|
324
|
-
|
|
322
|
+
released: 2026-06-03
|
|
325
323
|
summary: "Machine-readable site endpoints for downstream sites and AI agents."
|
|
326
324
|
features:
|
|
327
325
|
- "Auto-generated `/search.json` endpoint for downstream sites"
|
|
328
326
|
- "Auto-generated `/sitemap/` endpoint"
|
|
329
327
|
- "Ruby gem and Mermaid dependency updates"
|
|
330
328
|
|
|
331
|
-
# --- Future ----------------------------------------------------------------
|
|
332
|
-
|
|
333
329
|
- version: "1.13"
|
|
330
|
+
title: "Quality Framework — First Wave"
|
|
331
|
+
status: completed
|
|
332
|
+
section: Completed
|
|
333
|
+
start: 2026-06
|
|
334
|
+
end: 2026-06
|
|
335
|
+
released: 2026-06-11
|
|
336
|
+
summary: "First shipped wave of the Zer0-Mistake Quality Framework: CI gate parity and DOM sanitization."
|
|
337
|
+
features:
|
|
338
|
+
- "CI gate parity (T-012) — PRs run the full canonical test entrypoint, not a subset"
|
|
339
|
+
- "Admin config-page DOM sanitization (T-009), Liquid + plugin layers"
|
|
340
|
+
- "Release changelog single source of truth; workflow lint cleanup (T-017)"
|
|
341
|
+
- "Gate-coverage controls contract documented in the workflows README"
|
|
342
|
+
|
|
343
|
+
# --- Current ---------------------------------------------------------------
|
|
344
|
+
|
|
345
|
+
- version: "1.14"
|
|
334
346
|
title: "Zer0-Mistake Quality Framework"
|
|
335
|
-
status:
|
|
336
|
-
section:
|
|
347
|
+
status: active
|
|
348
|
+
section: Current
|
|
337
349
|
start: 2026-06
|
|
338
350
|
end: 2026-08
|
|
339
|
-
target: "
|
|
351
|
+
target: "Current (1.14.x)"
|
|
340
352
|
summary: "Close the gap between the repo's quality gates and what CI actually enforces — no mistake lands green."
|
|
341
353
|
features:
|
|
342
|
-
- "
|
|
343
|
-
- "
|
|
344
|
-
- "
|
|
345
|
-
- "
|
|
346
|
-
- "Coverage baseline with follow-up tasks for the lowest-covered subsystems"
|
|
347
|
-
- "
|
|
354
|
+
- "Re-armed docs lint gate on a zero-violation baseline (T-014)"
|
|
355
|
+
- "Locale-independence regression guard for the Ruby/Bash tooling (T-015)"
|
|
356
|
+
- "Strict site_generation suite — build failures fail the gate (T-016)"
|
|
357
|
+
- "Re-armed pixel-snapshot gate (refreshed baselines, no continue-on-error) (T-013)"
|
|
358
|
+
- "Coverage baseline with follow-up tasks for the lowest-covered subsystems (T-005)"
|
|
359
|
+
- "Navbar WCAG 2.1 AA fixes unlocking the axe-core full audit (T-007)"
|
|
348
360
|
|
|
349
361
|
- version: "2.0"
|
|
350
362
|
title: "CMS Integration"
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
<!-- Search modal controller -->
|
|
33
33
|
<script src="{{ '/assets/js/search-modal.js' | relative_url }}"></script>
|
|
34
34
|
|
|
35
|
+
<!-- Share helpers -->
|
|
36
|
+
<script src="{{ '/assets/js/share-actions.js' | relative_url }}"></script>
|
|
37
|
+
|
|
35
38
|
<!-- fffuel-style background customizer (skin switching, toggle, opacity) -->
|
|
36
39
|
<script src="{{ '/assets/js/background-customizer.js' | relative_url }}"></script>
|
|
37
40
|
|
|
@@ -46,6 +46,9 @@
|
|
|
46
46
|
{% assign file_path = page_dir | append: "/" | append: page.path %}
|
|
47
47
|
{% assign repo_parts = site.repository | split: "/" %}
|
|
48
48
|
{% assign repo_owner = repo_parts[0] %}
|
|
49
|
+
{% assign page_absolute_url = page.url | absolute_url %}
|
|
50
|
+
{% assign linkedin_share_title = page.title | default: site.title | strip_html | strip_newlines | strip %}
|
|
51
|
+
{% assign linkedin_share_description = page.description | default: page.excerpt | default: site.description | strip_html | strip_newlines | strip %}
|
|
49
52
|
|
|
50
53
|
{% comment %}
|
|
51
54
|
Resolve author display name and optional profile URL from page front matter,
|
|
@@ -233,12 +236,19 @@
|
|
|
233
236
|
</button>
|
|
234
237
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="shareDropdownBottom">
|
|
235
238
|
<li>
|
|
236
|
-
<a class="dropdown-item" href="https://reddit.com/submit?url={{
|
|
239
|
+
<a class="dropdown-item" href="https://reddit.com/submit?url={{ page_absolute_url | uri_escape }}&title={{ page.title | uri_escape }}" target="_blank" rel="noopener noreferrer">
|
|
237
240
|
<i class="bi bi-reddit me-2"></i>Share on Reddit
|
|
238
241
|
</a>
|
|
239
242
|
</li>
|
|
240
243
|
<li>
|
|
241
|
-
<a class="dropdown-item
|
|
244
|
+
<a class="dropdown-item js-linkedin-share"
|
|
245
|
+
href="https://www.linkedin.com/sharing/share-offsite/?url={{ page_absolute_url | uri_escape }}"
|
|
246
|
+
target="_blank"
|
|
247
|
+
rel="noopener noreferrer"
|
|
248
|
+
title="Copies a cleaned article summary to your clipboard, then opens LinkedIn sharing"
|
|
249
|
+
data-share-url="{{ page_absolute_url | escape }}"
|
|
250
|
+
data-share-title="{{ linkedin_share_title | escape }}"
|
|
251
|
+
data-share-description="{{ linkedin_share_description | escape }}">
|
|
242
252
|
<i class="bi bi-linkedin me-2"></i>Share on LinkedIn
|
|
243
253
|
</a>
|
|
244
254
|
</li>
|
|
@@ -332,4 +342,4 @@
|
|
|
332
342
|
</div>
|
|
333
343
|
</div>
|
|
334
344
|
</div>
|
|
335
|
-
</div>
|
|
345
|
+
</div>
|
data/_layouts/note.html
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
layout: default
|
|
3
3
|
---
|
|
4
|
+
{% assign page_absolute_url = page.url | absolute_url %}
|
|
5
|
+
{% assign linkedin_share_title = page.title | default: site.title | strip_html | strip_newlines | strip %}
|
|
6
|
+
{% assign linkedin_share_description = page.description | default: page.excerpt | default: site.description | strip_html | strip_newlines | strip %}
|
|
4
7
|
<!--
|
|
5
8
|
===================================================================
|
|
6
9
|
NOTE LAYOUT - Quick Notes and Reference Display
|
|
@@ -153,11 +156,17 @@ layout: default
|
|
|
153
156
|
class="btn btn-outline-primary btn-sm" target="_blank" rel="noopener noreferrer" aria-label="Share on X">
|
|
154
157
|
<i class="bi bi-twitter-x"></i> X
|
|
155
158
|
</a>
|
|
156
|
-
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{
|
|
157
|
-
class="btn btn-outline-primary btn-sm
|
|
159
|
+
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{ page_absolute_url | uri_escape }}"
|
|
160
|
+
class="btn btn-outline-primary btn-sm js-linkedin-share"
|
|
161
|
+
data-share-url="{{ page_absolute_url | escape }}"
|
|
162
|
+
data-share-title="{{ linkedin_share_title | escape }}"
|
|
163
|
+
data-share-description="{{ linkedin_share_description | escape }}"
|
|
164
|
+
title="Copies a cleaned article summary to your clipboard, then opens LinkedIn sharing"
|
|
165
|
+
target="_blank" rel="noopener noreferrer">
|
|
158
166
|
<i class="bi bi-linkedin"></i> LinkedIn
|
|
159
167
|
</a>
|
|
160
|
-
<a href="mailto:?subject={{ page.title | uri_escape }}&body={{
|
|
168
|
+
<a href="mailto:?subject={{ page.title | uri_escape }}&body={{ page_absolute_url | uri_escape }}"
|
|
169
|
+
title="Share this note by email"
|
|
161
170
|
class="btn btn-outline-primary btn-sm">
|
|
162
171
|
<i class="bi bi-envelope"></i> Email
|
|
163
172
|
</a>
|
|
@@ -381,7 +381,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
|
381
381
|
['--bs-border-radius', '--bs-border-width', '--bs-body-font-size', '--bs-body-font-weight', '--bs-body-line-height'].forEach(function (v) {
|
|
382
382
|
if (state.liveOverrides[v]) {
|
|
383
383
|
var key = v.replace('--bs-', '').replace(/-/g, '_');
|
|
384
|
-
lines.push('# ' + key + ': ' + state.liveOverrides[v]);
|
|
384
|
+
lines.push('# ' + key + ': "' + state.liveOverrides[v] + '"');
|
|
385
385
|
}
|
|
386
386
|
});
|
|
387
387
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function normalizeWhitespace(text) {
|
|
5
|
+
return (text || '').replace(/\s+/g, ' ').trim();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function dedupeSections(sections) {
|
|
9
|
+
return sections.filter((section, index) => {
|
|
10
|
+
if (!section) return false;
|
|
11
|
+
const normalized = section.toLowerCase();
|
|
12
|
+
return !sections.slice(0, index).some((previous) => previous && previous.toLowerCase() === normalized);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function truncateToSentence(text, maxLength) {
|
|
17
|
+
if (text.length <= maxLength) return text;
|
|
18
|
+
|
|
19
|
+
const trimmed = text.slice(0, maxLength);
|
|
20
|
+
const sentenceBreak = Math.max(
|
|
21
|
+
trimmed.lastIndexOf('. '),
|
|
22
|
+
trimmed.lastIndexOf('! '),
|
|
23
|
+
trimmed.lastIndexOf('? ')
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (sentenceBreak > Math.floor(maxLength * 0.6)) {
|
|
27
|
+
return trimmed.slice(0, sentenceBreak + 1).trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const lastSpace = trimmed.lastIndexOf(' ');
|
|
31
|
+
const endIndex = lastSpace > 0 ? lastSpace : maxLength;
|
|
32
|
+
return `${trimmed.slice(0, endIndex).trim()}…`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getShareContentRoot() {
|
|
36
|
+
return document.querySelector('[itemprop="articleBody"]')
|
|
37
|
+
|| document.querySelector('.bd-content')
|
|
38
|
+
|| document.querySelector('main')
|
|
39
|
+
|| document.body;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function extractCleanExcerpt(description) {
|
|
43
|
+
const contentRoot = getShareContentRoot();
|
|
44
|
+
const normalizedDescription = normalizeWhitespace(description).toLowerCase();
|
|
45
|
+
const paragraphTexts = Array.from(contentRoot.querySelectorAll('p'))
|
|
46
|
+
.map((paragraph) => normalizeWhitespace(paragraph.textContent))
|
|
47
|
+
.filter((paragraph) => paragraph.length > 40)
|
|
48
|
+
.filter((paragraph) => {
|
|
49
|
+
const normalizedParagraph = paragraph.toLowerCase();
|
|
50
|
+
return !normalizedDescription
|
|
51
|
+
|| (normalizedParagraph !== normalizedDescription && !normalizedParagraph.includes(normalizedDescription));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const combinedParagraphs = paragraphTexts.slice(0, 4).join(' ');
|
|
55
|
+
const fallbackText = normalizeWhitespace(contentRoot.textContent);
|
|
56
|
+
const candidateText = combinedParagraphs || fallbackText;
|
|
57
|
+
|
|
58
|
+
return truncateToSentence(candidateText, 420);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildLinkedInShareText(anchor) {
|
|
62
|
+
const title = normalizeWhitespace(anchor.dataset.shareTitle || document.title);
|
|
63
|
+
const description = normalizeWhitespace(
|
|
64
|
+
anchor.dataset.shareDescription
|
|
65
|
+
|| document.querySelector('meta[name="description"]')?.getAttribute('content')
|
|
66
|
+
|| ''
|
|
67
|
+
);
|
|
68
|
+
const excerpt = extractCleanExcerpt(description);
|
|
69
|
+
const url = normalizeWhitespace(anchor.dataset.shareUrl || window.location.href);
|
|
70
|
+
|
|
71
|
+
return dedupeSections([title, description, excerpt, url]).join('\n\n');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function copyShareText(text) {
|
|
75
|
+
if (!navigator.clipboard || typeof navigator.clipboard.writeText !== 'function') {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await navigator.clipboard.writeText(text);
|
|
81
|
+
return true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.warn('LinkedIn share copy failed:', error);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function openShareWindow(href) {
|
|
89
|
+
return window.open(href || 'about:blank', '_blank', 'noopener,noreferrer');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function notify(message, type) {
|
|
93
|
+
const notification = document.createElement('div');
|
|
94
|
+
notification.className = `alert alert-${type || 'info'} shadow position-fixed top-0 end-0 m-3`;
|
|
95
|
+
notification.style.zIndex = '1085';
|
|
96
|
+
notification.setAttribute('role', 'status');
|
|
97
|
+
notification.textContent = message;
|
|
98
|
+
document.body.appendChild(notification);
|
|
99
|
+
|
|
100
|
+
window.setTimeout(() => {
|
|
101
|
+
notification.remove();
|
|
102
|
+
}, 4000);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function bindLinkedInShare(anchor) {
|
|
106
|
+
if (anchor.dataset.linkedinShareBound === 'true') return;
|
|
107
|
+
|
|
108
|
+
anchor.dataset.linkedinShareBound = 'true';
|
|
109
|
+
anchor.addEventListener('click', async function (event) {
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
|
|
112
|
+
const shareWindow = openShareWindow('', '_blank');
|
|
113
|
+
|
|
114
|
+
const shareText = buildLinkedInShareText(anchor);
|
|
115
|
+
const copied = await copyShareText(shareText);
|
|
116
|
+
|
|
117
|
+
if (shareWindow) {
|
|
118
|
+
shareWindow.location = anchor.href;
|
|
119
|
+
} else {
|
|
120
|
+
window.location.assign(anchor.href);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (copied) {
|
|
124
|
+
notify('A cleaned LinkedIn-ready summary was copied to your clipboard. Paste it on LinkedIn after the share page opens.', 'info');
|
|
125
|
+
} else {
|
|
126
|
+
notify('LinkedIn opened, but clipboard access was unavailable. Copy the summary manually if needed.', 'warning');
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function bindCopyButton(button) {
|
|
132
|
+
if (button.dataset.copyBound === 'true') return;
|
|
133
|
+
|
|
134
|
+
button.dataset.copyBound = 'true';
|
|
135
|
+
button.addEventListener('click', async function () {
|
|
136
|
+
const copied = await copyShareText(button.dataset.copyText || '');
|
|
137
|
+
|
|
138
|
+
if (copied) {
|
|
139
|
+
notify(button.dataset.copySuccess || 'Copied to clipboard.', 'success');
|
|
140
|
+
} else {
|
|
141
|
+
notify('Clipboard access was unavailable.', 'warning');
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function initLinkedInShareButtons() {
|
|
147
|
+
document.querySelectorAll('.js-linkedin-share').forEach(bindLinkedInShare);
|
|
148
|
+
document.querySelectorAll('.js-copy-share-link').forEach(bindCopyButton);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (document.readyState === 'loading') {
|
|
152
|
+
document.addEventListener('DOMContentLoaded', initLinkedInShareButtons);
|
|
153
|
+
} else {
|
|
154
|
+
initLinkedInShareButtons();
|
|
155
|
+
}
|
|
156
|
+
})();
|
|
@@ -121,7 +121,9 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
|
121
121
|
lines.push('');
|
|
122
122
|
lines.push('theme_color:');
|
|
123
123
|
document.querySelectorAll('[data-color-key]').forEach(function (el) {
|
|
124
|
-
|
|
124
|
+
// Quote values: unquoted #RRGGBB is parsed as a YAML comment,
|
|
125
|
+
// silently dropping the color (T-008).
|
|
126
|
+
lines.push(' ' + el.dataset.colorKey + ': "' + el.value + '"');
|
|
125
127
|
});
|
|
126
128
|
var output = document.getElementById('theme-yaml-output');
|
|
127
129
|
if (output) output.textContent = lines.join('\n');
|
data/scripts/bin/validate
CHANGED
|
@@ -127,6 +127,7 @@ main() {
|
|
|
127
127
|
source "$TEST_DIR/test_changelog.sh"
|
|
128
128
|
source "$TEST_DIR/test_gem.sh"
|
|
129
129
|
source "$TEST_DIR/test_analyze_commits.sh"
|
|
130
|
+
source "$TEST_DIR/test_locale_independence.sh"
|
|
130
131
|
|
|
131
132
|
# Summary
|
|
132
133
|
echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Locale-independence regression guard (T-015)
|
|
4
|
+
#
|
|
5
|
+
# PR #132 fixed `invalid byte sequence in US-ASCII` crashes in the Ruby
|
|
6
|
+
# tooling that only reproduced when no UTF-8 locale was set (minimal
|
|
7
|
+
# containers, some CI runners). These tests run the validators under
|
|
8
|
+
# LC_ALL=C LANG=C so the bug class cannot silently return: the repo files
|
|
9
|
+
# they read (README.md, _data/*.yml, package.json) contain multibyte
|
|
10
|
+
# characters, so any locale-dependent File.read regresses to a crash here.
|
|
11
|
+
|
|
12
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
13
|
+
|
|
14
|
+
echo "Testing locale independence (LC_ALL=C LANG=C)..."
|
|
15
|
+
|
|
16
|
+
assert_true "(cd '$REPO_ROOT' && LC_ALL=C LANG=C ruby scripts/generate-roadmap.rb --check >/dev/null 2>&1)" \
|
|
17
|
+
"generate-roadmap.rb --check survives a C locale"
|
|
18
|
+
|
|
19
|
+
assert_true "(cd '$REPO_ROOT' && LC_ALL=C LANG=C ruby scripts/generate-roadmap.rb --validate >/dev/null 2>&1)" \
|
|
20
|
+
"generate-roadmap.rb --validate survives a C locale"
|
|
21
|
+
|
|
22
|
+
assert_true "(cd '$REPO_ROOT' && LC_ALL=C LANG=C ruby scripts/sync-backlog.rb --check >/dev/null 2>&1)" \
|
|
23
|
+
"sync-backlog.rb --check survives a C locale"
|
|
24
|
+
|
|
25
|
+
# validate --quick covers the package.json read in scripts/bin/validate
|
|
26
|
+
assert_true "(cd '$REPO_ROOT' && LC_ALL=C LANG=C ./scripts/bin/validate --quick >/dev/null 2>&1)" \
|
|
27
|
+
"validate --quick survives a C locale"
|
|
28
|
+
|
|
29
|
+
echo -e "\n${GREEN}locale-independence tests complete${NC}"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-theme-zer0
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amr Abdel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|
|
@@ -306,6 +306,7 @@ files:
|
|
|
306
306
|
- assets/js/posts-pagination.js
|
|
307
307
|
- assets/js/search-modal.js
|
|
308
308
|
- assets/js/setup-wizard.js
|
|
309
|
+
- assets/js/share-actions.js
|
|
309
310
|
- assets/js/side-bar-folders.js
|
|
310
311
|
- assets/js/skin-editor.js
|
|
311
312
|
- assets/js/stats.js
|
|
@@ -482,6 +483,7 @@ files:
|
|
|
482
483
|
- scripts/test/lib/test_changelog.sh
|
|
483
484
|
- scripts/test/lib/test_gem.sh
|
|
484
485
|
- scripts/test/lib/test_git.sh
|
|
486
|
+
- scripts/test/lib/test_locale_independence.sh
|
|
485
487
|
- scripts/test/lib/test_validation.sh
|
|
486
488
|
- scripts/test/lib/test_version.sh
|
|
487
489
|
- scripts/test/theme/validate
|
|
@@ -509,7 +511,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
509
511
|
requirements:
|
|
510
512
|
- - ">="
|
|
511
513
|
- !ruby/object:Gem::Version
|
|
512
|
-
version: 2
|
|
514
|
+
version: '3.2'
|
|
513
515
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
514
516
|
requirements:
|
|
515
517
|
- - ">="
|