jekyll-theme-zer0 1.19.1 → 1.20.2

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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +395 -0
  3. data/README.md +27 -19
  4. data/_data/authors.yml +154 -5
  5. data/_data/backlog.yml +5 -5
  6. data/_data/content_statistics.yml +273 -297
  7. data/_data/features.yml +4 -25
  8. data/_data/navigation/README.md +24 -0
  9. data/_data/navigation/about.yml +2 -0
  10. data/_data/navigation/main.yml +2 -7
  11. data/_data/roadmap.yml +86 -12
  12. data/_includes/components/author-avatar-url.html +28 -0
  13. data/_includes/components/author-bio.html +86 -0
  14. data/_includes/components/author-card.html +184 -121
  15. data/_includes/components/author-eeat.html +10 -4
  16. data/_includes/components/info-section.html +1 -1
  17. data/_includes/components/mermaid.html +0 -3
  18. data/_includes/components/post-card.html +19 -9
  19. data/_includes/content/giscus.html +3 -2
  20. data/_includes/core/footer-fabs.html +28 -0
  21. data/_includes/core/footer.html +7 -17
  22. data/_includes/core/head.html +2 -2
  23. data/_includes/navigation/breadcrumbs.html +20 -2
  24. data/_includes/navigation/local-graph.html +18 -2
  25. data/_includes/obsidian/full-graph.html +4 -6
  26. data/_layouts/article.html +44 -74
  27. data/_layouts/author.html +274 -0
  28. data/_layouts/authors.html +55 -0
  29. data/_layouts/news.html +3 -3
  30. data/_layouts/note.html +21 -6
  31. data/_layouts/notebook.html +21 -6
  32. data/_layouts/root.html +31 -17
  33. data/_layouts/section.html +3 -3
  34. data/_plugins/author_pages_generator.rb +121 -0
  35. data/_sass/components/_author.scss +219 -0
  36. data/_sass/components/_content-tables.scss +16 -1
  37. data/_sass/components/_notes-index.scss +102 -0
  38. data/_sass/components/_search-modal.scss +40 -0
  39. data/_sass/components/_ui-enhancements.scss +570 -0
  40. data/_sass/core/_docs-code-examples.scss +463 -0
  41. data/_sass/core/_docs-layout.scss +0 -453
  42. data/_sass/core/_navbar.scss +253 -0
  43. data/_sass/core/_sidebar-extras.scss +79 -0
  44. data/_sass/core/_toc.scss +87 -0
  45. data/_sass/core/_variables.scss +7 -142
  46. data/_sass/custom.scss +24 -1122
  47. data/_sass/layouts/_global-chrome.scss +59 -0
  48. data/assets/css/main.scss +19 -2
  49. data/assets/js/author-profile.js +190 -0
  50. data/assets/js/modules/navigation/navbar.js +104 -0
  51. data/assets/js/obsidian-graph.js +2 -2
  52. data/assets/js/obsidian-local-graph.js +11 -5
  53. data/assets/vendor/cytoscape/cytoscape.min.js +32 -0
  54. data/scripts/README.md +39 -0
  55. data/scripts/bin/validate +11 -1
  56. data/scripts/dev/css-diff.sh +49 -0
  57. data/scripts/dev/shot.js +37 -0
  58. data/scripts/features/generate-preview-images +110 -6
  59. data/scripts/features/pixelate-preview-images +126 -0
  60. data/scripts/features/pixelate_images.py +662 -0
  61. data/scripts/github-setup.sh +0 -0
  62. data/scripts/lib/preview_generator.py +47 -3
  63. data/scripts/pixelate-preview-images.sh +12 -0
  64. data/scripts/test/integration/auto-version +10 -8
  65. data/scripts/test/lib/run_tests.sh +2 -0
  66. data/scripts/test/lib/test_content_review.sh +205 -0
  67. data/scripts/test/lib/test_pixelate_images.sh +108 -0
  68. metadata +25 -20
  69. data/_data/hub.yml +0 -68
  70. data/_data/hub_index.yml +0 -203
  71. data/_data/navigation/hub.yml +0 -110
  72. data/assets/vendor/font-awesome/css/all.min.css +0 -9
  73. data/assets/vendor/font-awesome/webfonts/fa-brands-400.ttf +0 -0
  74. data/assets/vendor/font-awesome/webfonts/fa-brands-400.woff2 +0 -0
  75. data/assets/vendor/font-awesome/webfonts/fa-regular-400.ttf +0 -0
  76. data/assets/vendor/font-awesome/webfonts/fa-regular-400.woff2 +0 -0
  77. data/assets/vendor/font-awesome/webfonts/fa-solid-900.ttf +0 -0
  78. data/assets/vendor/font-awesome/webfonts/fa-solid-900.woff2 +0 -0
  79. data/assets/vendor/font-awesome/webfonts/fa-v4compatibility.ttf +0 -0
  80. data/assets/vendor/font-awesome/webfonts/fa-v4compatibility.woff2 +0 -0
  81. data/assets/vendor/jquery/jquery-3.7.1.min.js +0 -2
  82. data/scripts/lib/hub.rb +0 -208
  83. data/scripts/provision-org-sites.rb +0 -252
  84. data/scripts/provision-org-sites.sh +0 -23
  85. data/scripts/sync-hub-metadata.rb +0 -184
  86. data/scripts/sync-hub-metadata.sh +0 -22
data/_data/features.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # zer0-mistakes Theme Features Registry
2
2
  # Comprehensive feature tracking for the zer0-mistakes Jekyll theme
3
- # Version: 1.16.0
4
- # Last Updated: 2026-06-12
3
+ # Version: 1.6.2
4
+ # Last Updated: 2026-06-13
5
5
 
6
6
  features:
7
7
  # ============================================================================
@@ -1293,27 +1293,6 @@ features:
1293
1293
  references:
1294
1294
  includes: ["_includes/components/ai-chat.html"]
1295
1295
  layouts: ["_layouts/root.html"]
1296
+ scripts: ["assets/js/ai-chat.js", "templates/deploy/chat-proxy/worker.js", "templates/deploy/chat-proxy/dev-proxy.mjs", "templates/deploy/chat-proxy/page-store.mjs"]
1296
1297
  config: "_config.yml"
1297
-
1298
- - id: ZER0-061
1299
- title: "Org Content Hub (Federated)"
1300
- description: "Tooling to publish one GitHub Pages site per org repository — each renders its own content at <org>.github.io/<repo>/ with this theme via remote_theme — plus a /hub/ dashboard that tracks them all from GitHub API metadata. Content never leaves the source repo"
1301
- implemented: true
1302
- version: "1.17.0"
1303
- link: "/hub/"
1304
- docs: "https://github.com/bamr87/zer0-mistakes/blob/main/docs/systems/content-hub.md"
1305
- tags: [content, automation, ci-cd, navigation]
1306
- date: 2026-06-12
1307
- references:
1308
- scripts:
1309
- - "scripts/provision-org-sites.rb"
1310
- - "scripts/sync-hub-metadata.rb"
1311
- - "scripts/lib/hub.rb"
1312
- data: "_data/hub.yml"
1313
- workflow: ".github/workflows/hub-sync.yml"
1314
- docs: "docs/systems/content-hub.md"
1315
- features:
1316
- - "Provisions org repos as Pages sites (remote_theme) via PR — templates/org-site/*"
1317
- - "Auto-discovers org repositories via the gh CLI (registry: _data/hub.yml)"
1318
- - "Metadata-only dashboard — clones nothing, copies no content"
1319
- - "Dashboard at /hub/ shows each site's live/pending status and links"
1298
+ instructions: ".github/instructions/ai-chat.instructions.md"
@@ -42,6 +42,30 @@
42
42
  # nav: docs # Uses _data/navigation/docs.yml
43
43
  # ```
44
44
  #
45
+ # ## Navbar capacity & responsive constraints (main.yml)
46
+ #
47
+ # The top navbar adapts the `main.yml` items to the viewport automatically:
48
+ #
49
+ # - **≥ lg (992px+):** items render inline. The center track degrades in tiers
50
+ # as it gets crowded — full labels → ellipsized labels → icon-only — before
51
+ # anything is dropped.
52
+ # - **< lg:** the full menu moves into the slide-in offcanvas (hamburger), so
53
+ # item count and label length never affect the bar itself there.
54
+ #
55
+ # Guidance:
56
+ # - Aim for **~6–7 top-level items**. More still work, but on compact desktops
57
+ # (≈992–1200px) they collapse to icon-only and, past the track's capacity,
58
+ # would clip. Group extras under `children:` dropdowns instead of adding more
59
+ # top-level entries.
60
+ # - Long titles ellipsize rather than overflow; keep them short for legibility.
61
+ # - On local/dev hosts the navbar logs a `console.warn` ("[zer0-mistakes
62
+ # navbar]") when items don't fit or page content overflows the viewport — your
63
+ # cue that a config exceeds what the bar can show. (Silent in production.)
64
+ # - The theme also clips stray horizontal page overflow at the root, so an
65
+ # over-stuffed nav or wide content can never make the fixed navbar look "cut
66
+ # off". Wide tables/code keep their own local scroll. Regression-guarded by
67
+ # test/visual/navbar-responsive.spec.js.
68
+ #
45
69
  # ## Schema Validation
46
70
  #
47
71
  # Navigation YAML is validated at build time by _plugins/navigation_validator.rb
@@ -10,6 +10,8 @@
10
10
  children:
11
11
  - title: Overview
12
12
  url: /about/
13
+ - title: Authors
14
+ url: /authors/
13
15
  - title: Features
14
16
  url: /about/features/
15
17
  - title: AI Development Guide
@@ -51,13 +51,6 @@
51
51
  - title: Test Notebook
52
52
  url: /notebooks/test-notebook/
53
53
 
54
- - title: Hub
55
- icon: bi-collection
56
- url: /hub/
57
- # Per-repo links live in the generated sidebar (_data/navigation/hub.yml);
58
- # the navbar only needs the dashboard entry so new org repos appear without
59
- # touching this file.
60
-
61
54
  - title: Docs
62
55
  icon: bi-journal-bookmark
63
56
  url: /docs/
@@ -81,6 +74,8 @@
81
74
  children:
82
75
  - title: Features
83
76
  url: /features/
77
+ - title: Authors
78
+ url: /authors/
84
79
  - title: Statistics
85
80
  url: /about/stats/
86
81
  - title: Config
data/_data/roadmap.yml CHANGED
@@ -20,7 +20,7 @@
20
20
  # is internally consistent and still tracks the shipped gem version.
21
21
  # 4. Commit both this file and the resulting README.md changes.
22
22
  #
23
- # A GitHub Actions workflow (`.github/workflows/roadmap-sync.yml`) also runs
23
+ # A GitHub Actions workflow (`.github/workflows/sync.yml`) also runs
24
24
  # the generator and the validator automatically: it regenerates the README on
25
25
  # push, fails PRs whose README is stale, and flags whenever the roadmap drifts
26
26
  # behind the version in `lib/jekyll-theme-zer0/version.rb`.
@@ -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-12
63
+ updated: 2026-06-16
64
64
 
65
65
  milestones:
66
66
  # --- Completed -------------------------------------------------------------
@@ -340,23 +340,97 @@ milestones:
340
340
  - "Release changelog single source of truth; workflow lint cleanup (T-017)"
341
341
  - "Gate-coverage controls contract documented in the workflows README"
342
342
 
343
- # --- Current ---------------------------------------------------------------
344
-
345
343
  - version: "1.14"
346
344
  title: "Zer0-Mistake Quality Framework"
345
+ status: completed
346
+ section: Completed
347
+ start: 2026-06
348
+ end: 2026-06
349
+ released: 2026-06-11
350
+ summary: "Second wave of the Zer0-Mistake Quality Framework: DOM sanitization hardening and workflow lint cleanup."
351
+ features:
352
+ - "Admin config-page Liquid sanitization layer (T-009 hardening) — protects GitHub Pages builds where the plugin filter is a no-op"
353
+ - "version-bump.yml yamllint cleanup (T-017) — trailing spaces, bracket spacing, sequence indentation"
354
+ - "Changelog tooling: update_changelog_file normalizes trailing newlines and folds stale Unreleased sections"
355
+
356
+ - version: "1.15"
357
+ title: "Quality Framework Batch"
358
+ status: completed
359
+ section: Completed
360
+ start: 2026-06
361
+ end: 2026-06
362
+ released: 2026-06-12
363
+ summary: "Quality framework batch: docs lint baseline, locale guard, strict site_generation, contribution templates, and YAML export fix."
364
+ features:
365
+ - "Contribution templates (T-003): bug-report / feature-request forms, PR template with conventional-commit checklist"
366
+ - "Docs lint baseline + gate re-armed (T-004/T-014): ~1,600 markdownlint violations fixed, both `|| true` suppressions removed"
367
+ - "Theme customizer YAML export fix (T-008): hex color values quoted; frozen regression test promoted to live"
368
+ - "Locale-independence guard (T-015): validators run under `LC_ALL=C` in the lib test suite"
369
+ - "Strict site_generation suite (T-016): `jekyll build` failures now fail the gate"
370
+ - "Ruby gemspec floor raised to `>= 3.2` to match modern dependency requirements"
371
+
372
+ - version: "1.16"
373
+ title: "AI Chat + Consumer Audit"
374
+ status: completed
375
+ section: Completed
376
+ start: 2026-06
377
+ end: 2026-06
378
+ released: 2026-06-12
379
+ summary: "AI chat widget (ZER0-060) and consumer audit tooling; render guard bug fixed."
380
+ features:
381
+ - "AI Chat Assistant (ZER0-060): opt-in floating chat widget grounded in the current page with proxy-first auth"
382
+ - "Consumer audit tooling and theme manifest for downstream site health checks"
383
+ - "Chat render guard fix: Liquid `assign` truthy bug would have shown a dead FAB on every page"
384
+ - "Locale independence in `scripts/lib/frontmatter.sh` (multibyte post YAML errors under C locale)"
385
+
386
+ - version: "1.17"
387
+ title: "A11y, Mermaid & Migration Tests"
388
+ status: completed
389
+ section: Completed
390
+ start: 2026-06
391
+ end: 2026-06
392
+ released: 2026-06-12
393
+ summary: "Plugin unit specs, coverage baseline, config-page sync, WCAG 2.1 AA fixes, Mermaid on 12 more pages, and migration tests."
394
+ features:
395
+ - "Plugin unit specs (T-011): 19 Minitest specs for preview_image_generator, content_statistics_generator, admin_page_urls"
396
+ - "Coverage baseline (T-005): structural survey at docs/development/coverage-baseline.md; T-019/T-020 follow-ups filed"
397
+ - "Admin config-page sync (T-018): byte-synced copy, drift check in validate, Raw-YAML tab sanitized"
398
+ - "Navbar & site WCAG 2.1 AA fixes (T-007): all axe-core violations resolved; three test.fixme blocks promoted to live tests"
399
+ - "Mermaid on 12 more pages: missing `mermaid: true` front-matter flags added across the docs"
400
+ - "Obsidian graph view restored at `/docs/obsidian/graph/` (161 nodes, 269 edges)"
401
+ - "Migration & theme-version coverage (T-019): test_migrate.sh (14 assertions) and ThemeVersionGeneratorTest"
402
+
403
+ - version: "1.18"
404
+ title: "AI Content Reviewer"
405
+ status: completed
406
+ section: Completed
407
+ start: 2026-06
408
+ end: 2026-06
409
+ released: 2026-06-13
410
+ summary: "Two-tier AI content reviewer framework and chat GitHub action tools (issue/PR creation via Claude tool use)."
411
+ features:
412
+ - "Deterministic reviewer tier (`scripts/content-review.rb`): scores Markdown files 0–100 per-collection; posts sticky PR comment"
413
+ - "Claude Code agent tier (`.claude/agents/content-reviewer.md`): tone, clarity, consistency, accessibility review"
414
+ - "AI Content Review workflow (`.github/workflows/ai-content-review.yml`): runs on every PR touching `pages/**`"
415
+ - "Chat GitHub actions: file issues and open PRs via Claude tool use with in-chat confirmation cards"
416
+ - "Chat proxy template (Cloudflare Worker + Node dev proxy) with OAuth and API-key auth modes"
417
+ - "AI Chat rebuilt on the Claude Messages API (SSE streaming, `claude-opus-4-8` default)"
418
+
419
+ # --- Current ---------------------------------------------------------------
420
+
421
+ - version: "1.19"
422
+ title: "Site Hardening & Polish"
347
423
  status: active
348
424
  section: Current
349
425
  start: 2026-06
350
426
  end: 2026-08
351
- target: "Current (1.14.x)"
352
- summary: "Close the gap between the repo's quality gates and what CI actually enforces — no mistake lands green."
427
+ target: "Current (1.19.x)"
428
+ summary: "Production config hardening, analytics privacy fix, landing-page opt-out flags, and a documentation freshness sweep."
353
429
  features:
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)"
430
+ - "Config hardening: restored `zer0-mistakes.com` site identity + `CNAME` and the `remote_theme` contract (#174, #176)"
431
+ - "Opt-out flags for RSS link and visible landing-page title (`feat(home)`)"
432
+ - "Analytics fix: GA/GTM load only in production, skipping dev hostnames"
433
+ - "Documentation freshness sweep: broken cross-links repaired (T-004 follow-up)"
360
434
 
361
435
  - version: "2.0"
362
436
  title: "CMS Integration"
@@ -0,0 +1,28 @@
1
+ {%- comment -%}
2
+ ===================================================================
3
+ AUTHOR AVATAR URL RESOLVER
4
+ ===================================================================
5
+ Resolves an author's avatar image URL from an author data hash.
6
+ Pass the author entry (from _data/authors.yml) as `data`.
7
+
8
+ Resolution order:
9
+ 1. `avatar` is a full URL (contains "://") — used as-is. This is how you
10
+ reference an external avatar, e.g. a GitHub one:
11
+ avatar: "https://avatars.githubusercontent.com/u/10567847?v=4"
12
+ 2. `avatar` is a relative path (e.g. /images/authors/me.png) — prefixed with
13
+ the site's assets path ({{ site.baseurl }}/{{ site.public_folder }}).
14
+ 3. No `avatar`, but a `github` handle is set — falls back to that account's
15
+ GitHub avatar: https://github.com/<handle>.png
16
+ 4. Otherwise — empty output (the caller renders a fallback icon).
17
+
18
+ Output is the bare URL with no surrounding whitespace. Capture it (the example
19
+ below is brace-free so this comment does not self-execute):
20
+ capture avatar_url -> include components/author-avatar-url.html data=author_data
21
+ ===================================================================
22
+ {%- endcomment -%}
23
+ {%- assign _avatar = include.data.avatar -%}
24
+ {%- if _avatar and _avatar != "" -%}
25
+ {%- if _avatar contains "://" -%}{{ _avatar }}{%- else -%}{{ site.baseurl }}/{{ site.public_folder }}{{ _avatar }}{%- endif -%}
26
+ {%- elsif include.data.github and include.data.github != "" -%}
27
+ https://github.com/{{ include.data.github }}.png
28
+ {%- endif -%}
@@ -0,0 +1,86 @@
1
+ {% comment %}
2
+ ===================================================================
3
+ AUTHOR BIO COMPONENT - "About the Author" section
4
+ ===================================================================
5
+
6
+ File: author-bio.html
7
+ Path: _includes/components/author-bio.html
8
+ Purpose: Canonical end-of-content "About the Author" block, shared by the
9
+ article, note, and notebook layouts. Wraps the full author-card
10
+ primitive in a titled <aside> and links to the author's profile
11
+ page when the author resolves to a known _data/authors.yml entry —
12
+ either by key (default) or by display name ("Zer0-Mistakes Team").
13
+
14
+ Parameters:
15
+ - author (required): Author key from _data/authors.yml OR a plain name string.
16
+ - heading (optional): Section heading text (default: "About the Author").
17
+ - show_profile_link (optional): Show the "More from <name>" link when the
18
+ author is a known key (default: true).
19
+
20
+ Usage (wrap each line in Liquid include tags — braces omitted here because
21
+ Liquid parses tags even inside HTML comments, which would self-recurse):
22
+ include components/author-bio.html author=page.author
23
+ include components/author-bio.html author=page.author heading="Written by"
24
+
25
+ Gating: callers decide whether to render this at all — the article/note/
26
+ notebook layouts only include it when `page.author` is set and the
27
+ `author_profile` front-matter flag is not false.
28
+
29
+ Dependencies:
30
+ - components/author-card.html (style="full")
31
+ - _data/authors.yml
32
+ ===================================================================
33
+ {% endcomment %}
34
+ {% assign bio_heading = include.heading | default: "About the Author" %}
35
+
36
+ {% assign show_profile_link = true %}
37
+ {% if include.show_profile_link == false %}{% assign show_profile_link = false %}{% endif %}
38
+
39
+ {% comment %} Resolve the author to a known _data/authors.yml key — directly, or
40
+ by matching the display name / display_name — so the "More from" link works
41
+ whether front matter uses the key (default) or the name ("Zer0-Mistakes Team").
42
+ The profile URL is always built from the resolved KEY so the slug is correct. {% endcomment %}
43
+ {% assign bio_author_key = nil %}
44
+ {% assign bio_author_data = site.data.authors[include.author] %}
45
+ {% if bio_author_data %}
46
+ {% assign bio_author_key = include.author %}
47
+ {% elsif include.author and include.author != "" %}
48
+ {% for entry in site.data.authors %}
49
+ {% if entry[1].name == include.author or entry[1].display_name == include.author %}
50
+ {% assign bio_author_data = entry[1] %}
51
+ {% assign bio_author_key = entry[0] %}
52
+ {% break %}
53
+ {% endif %}
54
+ {% endfor %}
55
+ {% endif %}
56
+ {% comment %} Only build the "More from" profile URL when the author's profile
57
+ page exists in the build — generated author pages aren't delivered by
58
+ remote_theme, so the link would 404 on a Pages consumer. See issue #204. {% endcomment %}
59
+ {% assign bio_profile_url = nil %}
60
+ {% if bio_author_key %}
61
+ {% assign bio_author_name = bio_author_data.name | default: include.author %}
62
+ {% assign bio_author_slug = bio_author_key | slugify %}
63
+ {% capture bio_author_path %}/authors/{{ bio_author_slug }}/{% endcapture %}
64
+ {% assign bio_author_page = site.html_pages | where: "url", bio_author_path | first %}
65
+ {% if bio_author_page %}
66
+ {% capture bio_profile_url %}{{ site.baseurl }}{{ bio_author_path }}{% endcapture %}
67
+ {% endif %}
68
+ {% endif %}
69
+
70
+ {% if include.author %}
71
+ <aside class="author-section my-5 pt-4 border-top" aria-labelledby="about-the-author">
72
+ <h2 id="about-the-author" class="h5 mb-3">
73
+ <i class="bi bi-person-badge me-2" aria-hidden="true"></i>{{ bio_heading }}
74
+ </h2>
75
+
76
+ {% include components/author-card.html author=include.author style="full" %}
77
+
78
+ {% if show_profile_link and bio_profile_url %}
79
+ <div class="mt-3">
80
+ <a href="{{ bio_profile_url }}" class="btn btn-sm btn-outline-primary">
81
+ <i class="bi bi-collection me-1" aria-hidden="true"></i>More from {{ bio_author_name }}
82
+ </a>
83
+ </div>
84
+ {% endif %}
85
+ </aside>
86
+ {% endif %}