jekyll-theme-zer0 1.30.0 → 1.31.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +171 -0
  3. data/_data/backlog.yml +30 -7
  4. data/_data/consumers.yml +99 -0
  5. data/_data/features.yml +1 -1
  6. data/_data/theme-manifest.yml +35 -33
  7. data/_data/ui-text.yml +1 -0
  8. data/_includes/README.md +1 -1
  9. data/_includes/analytics/posthog.html +28 -9
  10. data/_includes/components/README.md +1 -1
  11. data/_includes/components/background-image.html +7 -1
  12. data/_includes/components/cookie-consent.html +30 -30
  13. data/_includes/components/mermaid.html +14 -7
  14. data/_includes/components/preview-image.html +22 -3
  15. data/_includes/components/theme-preview-gallery.html +1 -1
  16. data/_includes/content/intro.html +7 -0
  17. data/_includes/content/seo.html +8 -0
  18. data/_includes/content/sitemap.html +220 -263
  19. data/_includes/core/branding.html +8 -15
  20. data/_includes/core/head.html +29 -5
  21. data/_includes/core/header.html +14 -2
  22. data/_includes/core/tokens-inline.html +16 -1
  23. data/_includes/navigation/navbar.html +9 -6
  24. data/_includes/setup/wizard.html +5 -1
  25. data/_layouts/article.html +15 -3
  26. data/_layouts/home.html +13 -1
  27. data/_layouts/note.html +2 -1
  28. data/_layouts/notebook.html +2 -1
  29. data/_layouts/root.html +22 -0
  30. data/_sass/components/_cookie-banner.scss +48 -0
  31. data/_sass/components/_setup-wizard.scss +19 -1
  32. data/_sass/components/_ui-enhancements.scss +11 -0
  33. data/_sass/core/_navbar.scss +137 -70
  34. data/_sass/core/_sidebar-extras.scss +2 -14
  35. data/_sass/core/code-copy.scss +27 -8
  36. data/assets/css/extension-points-demo.css +27 -0
  37. data/assets/data/wiki-index.json +19 -0
  38. data/assets/js/auto-hide-nav.js +53 -13
  39. data/assets/js/code-copy.js +72 -1
  40. data/assets/js/extension-points-demo.js +48 -0
  41. data/assets/js/mermaid-diagrams.js +128 -22
  42. data/assets/js/obsidian-local-graph.js +27 -5
  43. data/assets/js/setup-wizard.js +7 -2
  44. data/scripts/ci/test_visual_evidence_autogen.py +64 -2
  45. data/scripts/ci/visual_evidence_autogen.py +14 -4
  46. data/scripts/features/install-preview-generator +1 -1
  47. data/scripts/lib/README.md +12 -0
  48. data/scripts/lib/preview_generator.py +2 -2
  49. metadata +4 -2
@@ -3,8 +3,8 @@
3
3
  # Regenerated automatically during each release (scripts/bin/release).
4
4
  # Consumers use this file via scripts/bin/audit-consumer to detect drift.
5
5
 
6
- version: "1.30.0"
7
- generated_at: "2026-09-12T15:18:42Z"
6
+ version: "1.31.0"
7
+ generated_at: "2026-10-07T21:57:46Z"
8
8
 
9
9
  # Directories owned by this theme. A consumer file in any of these paths
10
10
  # that is not declared in the consumer's .theme-overrides.yml is flagged
@@ -60,7 +60,7 @@ config_schema:
60
60
  file_checksums:
61
61
  _layouts/404.html: "47ef2766b6e9785316b40f221f42dda56e3b6654b1fd7362e20a300c70f53e80"
62
62
  _layouts/admin.html: "f8ea9d84e0947b6f7836c15bf715244e924192ce3a26f64a13d9d42c69281b37"
63
- _layouts/article.html: "c536d158ed96fce1880285b69b2bbf450eaa1023b3d0ba3cf6a298b9276c4156"
63
+ _layouts/article.html: "95ce1f0980aac1e1b5346a1ea12b630e8ede530d37f08a79e34be9103ab0b7e2"
64
64
  _layouts/author.html: "3739ccdcae4e4f63920801470571a4a243766a35bf68d8256012a8d142df42ca"
65
65
  _layouts/authors.html: "a0e1588c9e5a79abe95929aa6245ab64cdf04351e81e3d287d19f4fbd5548ac6"
66
66
  _layouts/book-abc.html: "0eaa068f75c573f0db8501e10c7ac0f9a74d4a738060d7a469fee7c1095c558f"
@@ -69,14 +69,14 @@ file_checksums:
69
69
  _layouts/collection.html: "9da7ac3209eb2e3e0980cbc934878e31a01fc1fd4be3871fdf4880a2f68b02ff"
70
70
  _layouts/cookbook.html: "f0ae3fcb1f07f3355fb5c876f2305873fb4a8cd457335dfd8f22e1856bc6bf56"
71
71
  _layouts/default.html: "4292cd641057a70d654407eb67eef8d6921692f1cf40b237f364f8f237c26c13"
72
- _layouts/home.html: "5cc357b1fbb8828abc7f25ec9bcd4a6a6d602d68c139ff6915fc1e0a7a06c612"
72
+ _layouts/home.html: "a67e0219abef4c78513c088004c39980e574d898c9dfeb5ad1522fd5edc292f8"
73
73
  _layouts/index.html: "82b543be5a911a0d48bccb25be1ee514eed6e8299dc4ae20d7ce7e08778d4bc0"
74
74
  _layouts/landing.html: "fbec896f0e75339a746bdb1a9a176ed66742d517c041a2bb89c3fd1f61512007"
75
75
  _layouts/news.html: "b5ac31019ba82a75ad45bfbbe613d85c1de9f2cf8432230297c2423283af23b1"
76
- _layouts/note.html: "47b019dbbe126952ba9b5f712c5c40653f978553e80cfde0aabd6abdfa987588"
77
- _layouts/notebook.html: "324c8b271be75cff3fbd8d15c7c71098249ec51d0cfa24fcaae96a4e19e3129e"
76
+ _layouts/note.html: "58b97dd42bb72c4b8ff18305287bddab8abf70969e87977252c9ae012b6bea0b"
77
+ _layouts/notebook.html: "2f3d24ebdc079a7ebfc8e1b77b86328fd4ee1512ce2047ac52acb9e814fba146"
78
78
  _layouts/recipe.html: "54b3c425fd198068fd15721c9828498aea440159105a9e5b38a1aaee62e87397"
79
- _layouts/root.html: "1a232af7b70aa02ed6eb02f81a4154f18d3267166d21ba08128725e490a62357"
79
+ _layouts/root.html: "cc7259c2bc8af60b613595fd5116849c95179853dc27c1384f849df66d67146d"
80
80
  _layouts/search.html: "b0b981d3233cab6f1ffec90c81a1340d251bd95a58bf2363d85bab5efe20ed95"
81
81
  _layouts/section.html: "662f332dccfe29bb85c44f224ae318b64bfa130e5edd60b56d1caa442f4e2bb9"
82
82
  _layouts/setup.html: "b3022e0766a8c288c0f2a618c013860a8cb7305b617b68727aff6bba924b7906"
@@ -87,7 +87,7 @@ file_checksums:
87
87
  _includes/analytics/google-analytics.html: "d67b99397df941b9bee165866c97f92c3cf6f247f76281e2126638ae3dc8647f"
88
88
  _includes/analytics/google-tag-manager-body.html: "7e37766982dc0b21d14683fa1f64f12c2f2eb500423edf6fa6184b1617788236"
89
89
  _includes/analytics/google-tag-manager-head.html: "4f52a13ff60a5eb099d3cbdeb756e44d2eac3bed214a7293f755f9f5aaa7ad20"
90
- _includes/analytics/posthog.html: "e35f6578eda64b3a8d83523f73f10024dc8fa27b2b5c7ac172107f95464c8268"
90
+ _includes/analytics/posthog.html: "869d09e36185a9dbbff68214fc800fa62e0a5c6100dff8619381cbce15017af6"
91
91
  _includes/components/abc-letter.html: "2a7765f39e0263ddb8ce7438dc159f25c6da6745c484a99c0b04b2a991dd8700"
92
92
  _includes/components/admin-links.html: "71fba67a292265f4074d254e7a8d90daab39f7a510ee3530f42681bb6c41981a"
93
93
  _includes/components/admin-tabs.html: "b75590a4c987440e35afeb96a62d569dc4f4c4ce5e91f966eacdef14ed28ddb0"
@@ -98,7 +98,7 @@ file_checksums:
98
98
  _includes/components/author-card.html: "5a3d64b0e5249977da6081f61a0753529f3dae58c5bacd1d03dbd1d7be78afd8"
99
99
  _includes/components/author-eeat.html: "0781fc9c2d70a72afeea915bcb457b33fc83eb5d8fae699e1857fbbe84abf53d"
100
100
  _includes/components/background-customizer.html: "e7c08df9456d09d96d0fb744ef3cb257905a4ef45ebcda9a4123c1ead6dfb28e"
101
- _includes/components/background-image.html: "5ecfca06f71b68999a5816f80d1314d71e30f939d0665d984e0efafe682d4755"
101
+ _includes/components/background-image.html: "745f8bb3c8fa0dcef0c5f687c015384bebeb60cd08029f924071bdcb09192231"
102
102
  _includes/components/background-settings.html: "b16dba76bf7a00533cb8f0782aea6005912bcf302837709fbc9d95ef39dfa087"
103
103
  _includes/components/book-card.html: "6b746548a9aa14de9e575ffc4e8ae874db4bb94e8e8064716d4953f26d1a4fef"
104
104
  _includes/components/book-nav.html: "9a6a85bbca4b16a7f50e50b4ec74d35b955f2095c4b56e714842041d17e92247"
@@ -111,7 +111,7 @@ file_checksums:
111
111
  _includes/components/component-showcase.html: "d36a006832bf0991d0a2540829bc9bad68b0af6aab13cf6e283d8f19e9e71b31"
112
112
  _includes/components/config-editor.html: "61c96ec4891966983839e4fcc68c77e5989dbc9d72c806706091b378b7f48b84"
113
113
  _includes/components/config-viewer.html: "dd88d0e8a311370c2a8c9605230940223db44c129b1d1adebc81915ef565b957"
114
- _includes/components/cookie-consent.html: "fa388050ea8b33bfdcb982a9b86c25dbad9970bcb2c5b2078395f066832f5597"
114
+ _includes/components/cookie-consent.html: "e8ea786e3420bd796da666b6d9aed5ec6c98aff13879f017b700ca23e557e103"
115
115
  _includes/components/cta-button.html: "a4352d9d4b43e0cb3c8fcf2c70569ec1a46029ab733a063a3e16be8bdc6c7501"
116
116
  _includes/components/data-card.html: "c46604f61bffab476bb943f4a631320077cb47b6a58a12e14aea7bc5118f80ac"
117
117
  _includes/components/dev-shortcuts.html: "32d430d109474d6136969b7f9ea1dc8b07386856e14a5829e22ac2c9102aa6f2"
@@ -123,7 +123,7 @@ file_checksums:
123
123
  _includes/components/info-section.html: "39b2d89723513614fc3579c6b524376cbbf854a3b4f62fa4c68a44e56dcda1a0"
124
124
  _includes/components/js-cdn.html: "bdbcea871586a63800e544750806facc191d8702b70291577999680699a69519"
125
125
  _includes/components/language-toggle.html: "1259f824c4e0055ae087ec6ea3593f8f6cf9b43da84a3a95fa9c5b5a6b50f464"
126
- _includes/components/mermaid.html: "e79bfeda232f5154da74f5c5f0cbcae0a47b804f69514bc48115a249a902d687"
126
+ _includes/components/mermaid.html: "df21aadd1bef7b40a6f714b975fddd439d0722481259dc9af27998aa51a1775a"
127
127
  _includes/components/nanobar.html: "a35128d8376d1dff44c34e42aceefc927c14f44f6f263102ef9f5d4c8a20db84"
128
128
  _includes/components/nav-editor.html: "51dde98e848c44cf464ea16308d965a3424706008119fab14fd181ddbf5067c0"
129
129
  _includes/components/nav-export.html: "11d56e16f29a6d51ce6816e87de348019eb56bb820fa23a184c4e1639da3fac0"
@@ -134,7 +134,7 @@ file_checksums:
134
134
  _includes/components/post-card.html: "d93a021a9c2e979bf3d7d741281ce4a15ec115c2b8b6a5a1bcc40e9a187959c2"
135
135
  _includes/components/post-type-badge.html: "4cb5f296c25b5340445ec9b52954644280877f004654a43ae78337d12745f517"
136
136
  _includes/components/powered-by.html: "d31ddf99fe16d9f946fa2fc98957544033bc41f8345c7401cbc5d018866c9194"
137
- _includes/components/preview-image.html: "db6e6839f0fa2c367ddb8daad5420793eef82cce312515af86204bab0d42ee13"
137
+ _includes/components/preview-image.html: "80c024a6f18dd4f623cbcde758fd66d28c7a4bbdb19a0cb53fa1999d99d654ea"
138
138
  _includes/components/quick-index.html: "19603453455fbf759ada8534dcac6df41ffbbf1122bc7f62b6b3748da604f43c"
139
139
  _includes/components/recipe-card.html: "c5600da464577d76baa377bf23c56fd13bca08c5455d22018301e9b9d07318cb"
140
140
  _includes/components/recipe-duration.html: "623709e34d29df7dbdc8226e1fa6f5c079048e1c8fe1c7d7e94a51ee5b5fb730"
@@ -160,29 +160,29 @@ file_checksums:
160
160
  _includes/components/theme-controls-bar.html: "53fe86978d1c9a13853fca0502c356b559640f67e11334fe27b180a6fd31d425"
161
161
  _includes/components/theme-customizer.html: "115030770a897e813a42108aa40794617fc5bc34fc39f41e77ed200f96d61cab"
162
162
  _includes/components/theme-info.html: "45121f886e48214106391fb89ac4c11ed5618b3730e41f21d1002ae325999851"
163
- _includes/components/theme-preview-gallery.html: "acffb55a6122b40f0ce3e3c64e6847d488f75d42d6df11d86d846862cc9a6de7"
163
+ _includes/components/theme-preview-gallery.html: "8a2f2c86f12ae141f77943c4beb36f06b20f423ce0e6669d53c6e82562edad65"
164
164
  _includes/components/translation-notice.html: "01e5d23801d454641b49f1a1efe83cc09089decdb61da14045f158f1b097e819"
165
165
  _includes/components/zer0-env-var.html: "d11f3a578319f48f763b0e8639230e71b9a6e9301453c73c9907814f086fc03e"
166
166
  _includes/content/backlinks.html: "6b18741876a3923606b60f60b3f366c3f60d49924d03a2b86c80df41f2e8130a"
167
167
  _includes/content/giscus.html: "8c49d8a22caef89a3132ba9da5434ddecf33b615f051eee1af7441df0bfef686"
168
- _includes/content/intro.html: "48482d4557575bb9345251a8694e4dc5d39df1b0a47a4c2103c153d37d35f337"
168
+ _includes/content/intro.html: "6777503c9c5f547012673379c0492db219e40898c24268312c2d0478208e34c0"
169
169
  _includes/content/jsonld-faq.html: "9e4001c9ccebb91ac1b2e51a8a7833e611bd70ae59fee7c599a88597b079a55c"
170
170
  _includes/content/jsonld-software.html: "41624ca1a61687a91878e4147cb6e1fc172ace09bf2d9688e5f1da16cdaecf06"
171
- _includes/content/seo.html: "b0ffb6e3b2c376fa985c4a8a0709caab22a7d68f65469f77361c9431262f4c51"
172
- _includes/content/sitemap.html: "7a9fa68da5073fc7ee0ba4942fb730a7cf8389d95f61e7b36f2247ec018f21ba"
171
+ _includes/content/seo.html: "05a6c4bb5aa9357facd041b85eb3ffc3b1ab0c4fabe7cbfa87f9905618718d5f"
172
+ _includes/content/sitemap.html: "d2504f4573d1978134d54751f63939f13a10efe0b5996267ccf2a6e3d13df589"
173
173
  _includes/content/toc.html: "b42a00a641db03b4936d4d754a2e14fcf9517c2b8e0257ceba8a6fe2e2003e40"
174
174
  _includes/content/transclude.html: "da0714fb23034e1499920fa7fe7f6ef58c4b98eeea40319d6f10361db99ea754"
175
- _includes/core/branding.html: "8dad883322fef029ec164800dad73d557af20e3ac715569f880f6e3c8fa3b120"
175
+ _includes/core/branding.html: "3e5d00bc427eb12585f77f98990e59f6dae8643eddfa395c7ac365b3d7cc680c"
176
176
  _includes/core/color-mode-init.html: "de31274204b6c5dea7e953f94e6663890a47286728484ee937b723100bf899ca"
177
177
  _includes/core/console-capture.html: "f9ca43e114faa48f6e76928b75b8baf580b6adb7efabf206a3b319938eabf019"
178
178
  _includes/core/favicon.html: "9ba9fc5b55f319c4af0404058eb5a3893eba52fe46cc48438037debe4baef458"
179
179
  _includes/core/footer-fabs.html: "4c46914fc53f3c40220501a34ffe20bb296d9f8ddeeec21e959b024f9a30e8a7"
180
180
  _includes/core/footer.html: "c41a421da9ae7df4116d9f0d544de0991d6fd612312986d68c5b7da17003adab"
181
- _includes/core/head.html: "2d266de582fbf26b31ec364d37b6ac234c3896f1d36b772f8805e54b9c3edb1e"
182
- _includes/core/header.html: "196a5852c68af49ce4a7a5ed6488feb7d50f8a69ba4b005bcf1d7cd2692d0e32"
181
+ _includes/core/head.html: "4a96a374e01afe5e41437edce7767c811564a90b6e0858d5aada8c68b19f17fc"
182
+ _includes/core/header.html: "10e4112f6d6c6f7a6c76a35e03aed48183eebfa7dc4887c02927eb8eb487f105"
183
183
  _includes/core/hreflang.html: "876c44ae392aace73680fb042b8cf7d2d1c2b3143dc755c4dd4c2eb5091356d1"
184
184
  _includes/core/i18n.html: "e856ab288f48a5f5f71941a8f47f7dde538deb64d513b57bdd7f4c1b1b2cd6b0"
185
- _includes/core/tokens-inline.html: "a406ea837bbb14437c674c9c73fc1c458863e66fdb3f44309aa2feeab9dfb83a"
185
+ _includes/core/tokens-inline.html: "d5388ac882d6e39e8e415e3739c80ef84fd4e79e3b86c0da068fa992a4a08da0"
186
186
  _includes/custom/body-end.html: "28dc02ba671178a8f673ea844b00a8750e30a5d949d7a8e2b26b83e156ac4ae0"
187
187
  _includes/custom/body-start.html: "62984bd5bcc8014be50b2fdc115b7e2f8e20462d73547616e4f9031f5dee0869"
188
188
  _includes/custom/footer.html: "d33cbad68c6038a795debf5ba182481f3b40f1c390a13a7a865ad70f04f3c9f5"
@@ -197,7 +197,7 @@ file_checksums:
197
197
  _includes/navigation/nav-tree.html: "d3002ad767eab6f27d9f252545f7564afc470b827ad67b7fb27fab90df9d124d"
198
198
  _includes/navigation/nav_list.html: "3450b282840fb5a82e0ab01d636e3b38e0bdbcc4233cca3e2f2a80fc7c71e3c5"
199
199
  _includes/navigation/navbar-mobile-quicklinks.html: "a2c23bbc41f8b27eae1a869893f1e7ecf881f12e34164ab7f8dc4a178011a45e"
200
- _includes/navigation/navbar.html: "d7bce9b784062f391321bbbb26a65737b7b30ee1886cfa040af98285aef2d059"
200
+ _includes/navigation/navbar.html: "2b2d4446c6be4ed5003cf482a116458858af919f61521d8f89cf1f70adadea68"
201
201
  _includes/navigation/section-sidebar.html: "d77e8328f818a161449263d8293876a53fa0261747949901cf2e19ff6ac2c2b2"
202
202
  _includes/navigation/sidebar-categories.html: "42217519bc109e030b8f6e2578783efbc13838176e0eeba7cc1450641eb2f641"
203
203
  _includes/navigation/sidebar-config.html: "40e8bf838a3f819ba65ddad8bd004aeb01a9abc5c5d35a6894ffb18aa798ce24"
@@ -212,7 +212,7 @@ file_checksums:
212
212
  _includes/search-data.json: "1824d7a8ed778cdab23c502098cfce7dc687c18cede989294dbc989bfb15187e"
213
213
  _includes/setup/claude-session.html: "cc7459d6c3ecb846cddabf039ddf5e90afa54429a8dea7ed27f3574fe0a9c7e5"
214
214
  _includes/setup/prereq-checklist.html: "f6af6ac1d32837399cdb223593f3024db5aab13a4987e179e1e711863625d05f"
215
- _includes/setup/wizard.html: "1b92a09ab231413ef60c6fb3491b20b42e0350a6c2a6032f8f3a6e5522d520be"
215
+ _includes/setup/wizard.html: "e3c94b8bf27789cd8e9992018ec7f4caa94628189d281acd8a85d565d7a51594"
216
216
  _includes/stats/stats-categories.html: "f9edb65068c846a973b27f2a07b582473e6ac0b0221793408fa0191082fd693d"
217
217
  _includes/stats/stats-header.html: "4f965b4a3f97d4eab8b2bb003558f7a05a99fd6a2f21e6a527e0ae30b6344ee5"
218
218
  _includes/stats/stats-metrics.html: "53066bb49d3070d842971e5ced2a394eba54f8aea80e35820ab41edfc8c979be"
@@ -224,7 +224,7 @@ file_checksums:
224
224
  _sass/components/_book.scss: "dd822c0d0cf84bb919d5b889a19cd75af4dc3603bd142e2b01c953c6b8e159f0"
225
225
  _sass/components/_callout.scss: "a17bf67c19c90ad791255c39c69c9796406c9feba40fa0ef62eeabcc1a5d8778"
226
226
  _sass/components/_content-tables.scss: "463fe822b6c885a3d4ee7ed94dca54c81001a2f346c61f1495f1334b89af12bc"
227
- _sass/components/_cookie-banner.scss: "8871eb995ac6389cda7f8fde5536899a551ffaa72ae67dff2c892ec7e2e056c2"
227
+ _sass/components/_cookie-banner.scss: "c2e0f314e5a65b91e5aa9af778d482e6f7888c08434ca3a41c76f5877edf03f7"
228
228
  _sass/components/_footer.scss: "aeda30d678adf29cfb9a052fe0faba2cdaf00f289fe3017cab309b5cfb74fb99"
229
229
  _sass/components/_mermaid.scss: "02de7801b8c82b160c312ac97cf0870e36fa7899cd1d698a46b6488ef669ac23"
230
230
  _sass/components/_notes-index.scss: "7abb34307cba043e3100a0c4311b9eb279b7dfdd42ea3a44631d7b6eda47b9fe"
@@ -234,23 +234,23 @@ file_checksums:
234
234
  _sass/components/_post-navigation.scss: "4d0a6d4a177d382297be352d0105658c30beac78ed4aef098b4ebdd835f8ae72"
235
235
  _sass/components/_recipe.scss: "f2d698fed00e0f789914ff3ba681d11ec82e0b28cd852ba1779a30a2cf0b7408"
236
236
  _sass/components/_search-modal.scss: "3460f554bfcb411bdd3476b9678661b896b9441368fbcf717ff375a0f6116043"
237
- _sass/components/_setup-wizard.scss: "dfbd7c183d73b0006ce23a38d0505710bcb855fff1dc8a48f1d72014e4c0c0f4"
237
+ _sass/components/_setup-wizard.scss: "57a4d3b4aa49c9cc02226b8716eacc2bdca46a2456867887d30dece18603543b"
238
238
  _sass/components/_skeleton.scss: "581407adc0e987d06d1a2a34cae36643cb94e7ab678b14d0d587e048e3e142bf"
239
239
  _sass/components/_theme-preview.scss: "eefdc6853e7fd3ff4ba9354e002261d13b608c021f5ce01c20f7cd10d553f6f4"
240
- _sass/components/_ui-enhancements.scss: "d6ad4941702434301c90285f587a59b206a669d302b59f278dfd0eff0a822386"
240
+ _sass/components/_ui-enhancements.scss: "1d1a2e32c232b9e015dfe5927bcbe1378cb58b650e6d0d159f193d85bba509c9"
241
241
  _sass/core/_docs-code-examples.scss: "422d704a7009a07115beede2fb4f925131859075b40d5aa10d0d73ca0ebca371"
242
242
  _sass/core/_docs-layout.scss: "adb29a60417ec2d13dd93501e6072d93ec021281de9711ed44fa76f4587def6f"
243
243
  _sass/core/_nav-tree.scss: "b696b2c5fd91dd5180010c59b38e5242c3b7a7258e889fc3c1ca16c2a53310c2"
244
- _sass/core/_navbar.scss: "8a8f798bcb3fe9e4e23844613225c41271c6aed51c0d5edf841f4ef080c6a4ed"
244
+ _sass/core/_navbar.scss: "52f447c560da18954932675290b2d39360a9c5be6f9fae8c0d3b62ef2ac11b28"
245
245
  _sass/core/_obsidian.scss: "557582682f3b37f6cbb3bac36ef2a90390d71604ef172262b5742d0c1aeba55b"
246
246
  _sass/core/_offcanvas-panels.scss: "f4c9e1046923ce036108424c7a9eeae92a54a4e95b31274283b6abf170fc846c"
247
247
  _sass/core/_sidebar-categories.scss: "7d75034b075f78dc3c604ccd190e25f98989a8162339ad9e837df82d57870eec"
248
- _sass/core/_sidebar-extras.scss: "24c7987e5c2ececfe20125eec43e62aa15f10a06af5df616d32d4009032a0415"
248
+ _sass/core/_sidebar-extras.scss: "346c757420504280a51cdf1f18577b8e29c7697bac7c1b8fe1edce67619a77f3"
249
249
  _sass/core/_syntax.scss: "f8612542c7adfb0bbc3e74920478a906825b429c1f46b7797b116b0d871a09be"
250
250
  _sass/core/_theme.scss: "343f8ff86fffcf87b8865325748aae48e7c9f70c6462f7e40063631593c3fabd"
251
251
  _sass/core/_toc.scss: "6193edabaf384f520827ab1175a8db1f8afff8346b24290d1eb2c5aa982589c6"
252
252
  _sass/core/_variables.scss: "d51e2890ed7feed30c73a8915500cb39b6bc4a63863731220518e7b73ab3ba55"
253
- _sass/core/code-copy.scss: "4ce91892327c6d5e8574e8f3f230f9886194dd5e712a7ec5816e8afed09f8ba5"
253
+ _sass/core/code-copy.scss: "23c2298598e589c5f065eb13435fda8326edf739e716198fc33b8523134a8683"
254
254
  _sass/custom.scss: "32ad90b7934dbfd9a865e0fab37acdf48ffd496c3b9af220e38e47d413ce6395"
255
255
  _sass/layouts/_global-chrome.scss: "d181cc70973d5623f4c92e9543e05d3217efe40321a63e765604a17df09debc5"
256
256
  _sass/layouts/_landing.scss: "0364dd6673b36fe9c9500cc9b71162114312c35a4289af8f9c2a6f7cfcfc9cc3"
@@ -276,23 +276,25 @@ file_checksums:
276
276
  _sass/utilities/_layout.scss: "3f12b385c2b14c603e7a4e055bee862c9635c2c16f40bca0d709851a0dc03efb"
277
277
  _sass/utilities/_motion.scss: "21441bdb990d961acbe2101ee361fc6b7338ffd815a1c0f0a84bf516d74440fe"
278
278
  assets/css/custom.css: "5b74a5e7282f09e17bb8105c144bcfd779efd29b4438f4eeb52ce7126a09d55f"
279
+ assets/css/extension-points-demo.css: "ec3762db165670a0d028a24474fdd646214b3b5e4e8d3b9ac6a319f63d20fc1e"
279
280
  assets/css/main.scss: "19caaffa9b960d9ddc501c7bde1eb23cb476a4660f98167e9bc7cb0774c7d6db"
280
281
  assets/css/stats.css: "3ac66f83fd3322a2fe98dbd5bc2d3ddc9a72071040699070478b90b12ac201c0"
281
282
  assets/css/theme-npm-entry.scss: "efb7b2ba4f419ad37d7a0b9cc93452d5ae9edc554e5bd03b9f2efb447c767079"
282
283
  assets/css/vendor/.gitkeep: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
283
284
  assets/js/ai-chat.js: "7521e4ec5a0db443a7ab1431878272aa594026ddecccf22e9c9d3db15464c593"
284
285
  assets/js/author-profile.js: "859502082032cb21a0ac9d972e69907fd5db9f5aaccca0a30f9b5a4c9e573262"
285
- assets/js/auto-hide-nav.js: "1d7efe2f342566c6ce8fd14b3ca10f98478bfdbbb61ecffa1a87a8532681303e"
286
+ assets/js/auto-hide-nav.js: "d63190049f90b206614a111ec664f3cd2f1c5698c0948f34c2173e28d15151bf"
286
287
  assets/js/back-to-top.js: "1d9b300881e4e80b3106e80c01804b6c34fbe3e89589fd399868431f65f7e5e2"
287
288
  assets/js/background-customizer.js: "eaed475eba55a8832ac41515260507bb7b6a202914b0f032117c13cb467ada7f"
288
289
  assets/js/cheetsheet.js: "79b33c7f404ac25b445b36da3bb5afd528389858ea811ac8d59d10007db1d5e6"
289
- assets/js/code-copy.js: "6f0ec270f41ed4f1bae74110c1db16ef3fb4a60e667bec4ab8f48946ec63f9e3"
290
+ assets/js/code-copy.js: "1fe5d4f3199df1b2f9f493e83b84920292028b8810adc1ab46fa0e69eaccc4aa"
290
291
  assets/js/config-utility.js: "a69f5dfcdf72464b0303ce3532a96a32b52825e903fd8fb7baab8cd2c8e5f319"
291
292
  assets/js/docs.min.js: "11a7ba4860a3e7688dc4b65aded12825219512d5baafa532fea7986909be4725"
293
+ assets/js/extension-points-demo.js: "e86712b6157d47c4e8760799fe896ea3b2f560bf5cd108745c2475a29b819edc"
292
294
  assets/js/fleet-feedback-capture.js: "f51b99aea37b9a41b00bfa9acc071b4e871999359e82d1e4b358af0eef743892"
293
295
  assets/js/fleet-feedback.js: "61b5aa0a49c6465fbab1f1f34e3ac1f0a3d627e418e554bf2ea1366b92fd124a"
294
296
  assets/js/halfmoon.js: "472650069d16004a9635edcefa1e60e0771e20ec5de9464b7bcf5220d20604d1"
295
- assets/js/mermaid-diagrams.js: "65ab6d3b0b51efe615a1635cf0e22cc27c6a87eb52863e6b5082dff11a8d200d"
297
+ assets/js/mermaid-diagrams.js: "c04d934109af0a4653ad30cb1d22913cea982e430cdf384f9f692b296352cd23"
296
298
  assets/js/modules/navigation/config.js: "226f341b4d0c7ef2b6a4eb98f5ab1ba9d626a9a24a9c66d889f1b3da3e0ad9f5"
297
299
  assets/js/modules/navigation/focus.js: "cd73b2bf9d6701a35f075a6304ebf92173c4b89eb021ce8df594e27e173528ca"
298
300
  assets/js/modules/navigation/gestures.js: "9fded02fe6d3ce429793e5b10e9a59317c5d9bccf81076d88718ae2eb07716ae"
@@ -311,7 +313,7 @@ file_checksums:
311
313
  assets/js/nav-editor.js: "4baa58537bdd0685341f20b4b0abbc22b313bf9ddc74c3b9e01fc8bc0e3585da"
312
314
  assets/js/navigation.js: "3442bcd0ebd2b11dc066ffd8faabc30cc4c5541089f06000fe91c95018939b50"
313
315
  assets/js/obsidian-graph.js: "94847c3e50c760478c8762913bfbd85e73a229ef33aaaab68b0361c3ea239408"
314
- assets/js/obsidian-local-graph.js: "2a1bc1397c7488416d726fec79f44f049ba1d066f15488f00ec46d585f6cea28"
316
+ assets/js/obsidian-local-graph.js: "8b70d8b2e0f85056451e16ef758d94cde3b245013f3792a53f4099dab9aa1a58"
315
317
  assets/js/obsidian-wiki-links.js: "fb3f7d142008110b95dc234ff910041e99618744345f000e2a03280319a36dc1"
316
318
  assets/js/page-feedback.js: "98fbed1134f3b2642d45e1ea27e1e4032ea84ca76ecc0542c6cc3314636f6ee4"
317
319
  assets/js/page-views.js: "27961f139f2b6656251ec3a1745beade1f96d2f36718f78cc533beb520919cb6"
@@ -321,7 +323,7 @@ file_checksums:
321
323
  assets/js/posts-pagination.js: "ed4b98bd1c958766ce604175bbef0681f7bc70d6b9bb306907f2ac676baf36f8"
322
324
  assets/js/recipe-scaler.js: "b05aa0cd0fafeadbf4454c4cacf1463f994e263a1f4a79a1d177f35a560a1e6e"
323
325
  assets/js/search-modal.js: "f94efe1fde116d2cfd163d7eb5882b43405f83bfd3f605af28c7cb786460d08a"
324
- assets/js/setup-wizard.js: "79dab7cce190c7842b260f9378b8e38852b3478814e378c31bffd289ef7d7e02"
326
+ assets/js/setup-wizard.js: "0ef2dcce4d93e753326999c7360dedda7b7d5b05cec2a52350b0110d0e583d0a"
325
327
  assets/js/share-actions.js: "810a326d8aa33633854364d91caddfff1c769eaa7d437a746f96a752c2e2fdae"
326
328
  assets/js/side-bar-folders.js: "133606c23a03b9370308811e0a39187f4dd43b487628f8d875ac631afa28598a"
327
329
  assets/js/site-builder.js: "d133bc799bf84094f748f99f44b7ed166c4095d69d6cd28dd98b9fc3cc435ada"
data/_data/ui-text.yml CHANGED
@@ -26,6 +26,7 @@ en: &DEFAULT_EN
26
26
  breadcrumb_home_label : "Home"
27
27
  breadcrumb_separator : "/"
28
28
  menu_label : "Toggle menu"
29
+ nav_menu_toggle_label : "Menu"
29
30
  search_label : "Toggle search"
30
31
  toc_label : "On this page"
31
32
  ext_link_label : "Direct link"
data/_includes/README.md CHANGED
@@ -59,7 +59,7 @@ Reusable UI components and widgets:
59
59
  - `post-card.html` - Reusable post card component for listings
60
60
  - `page-views.html` - Inline "N views" badge for a page (hidden until a count is known)
61
61
  - `page-views-init.html` - Page-view counter bootstrap: injects `site.page_views` config and loads `assets/js/page-views.js` (included once from `core/head.html`)
62
- - `mermaid.html` - Mermaid loader for pages with `mermaid: true` (included from `core/head.html`): injects `site.mermaid` config + translated toolbar labels and loads the vendored bundle and `assets/js/mermaid-diagrams.js`, both deferred. Every ```` ```mermaid ```` fence becomes a figure with a zoom / fullscreen / copy / download toolbar, an `accTitle` caption, token-derived colours, and an error card that keeps the source
62
+ - `mermaid.html` - Mermaid loader for pages with `mermaid: true` (included from `core/head.html`): injects `site.mermaid` config + translated toolbar labels and loads `assets/js/mermaid-diagrams.js` (deferred), which injects the vendored bundle only when a diagram is present and nears the viewport. Every ```` ```mermaid ```` fence becomes a figure with a zoom / fullscreen / copy / download toolbar, an `accTitle` caption, token-derived colours, and an error card that keeps the source
63
63
  - `data-card.html` - One generic card rendered from a plain data hash (title/url/icon/badge/meta/buttons schema in its header)
64
64
  - `card-grid.html` - Responsive grid of `data-card`s from any data array — hub dashboards, fleet registries, service grids
65
65
  - `bookshelf.html` - Grid of every book in the `books` collection (home-page library)
@@ -100,8 +100,24 @@ Privacy: Respects Do Not Track and provides opt-out mechanisms
100
100
  (window.posthogConfig.respectGpc && window.navigator.globalPrivacyControl === true)) {
101
101
  console.log('PostHog: respecting browser privacy signal (DNT/GPC)');
102
102
  } else {
103
+ {% comment %} Deferred loading: the stub below is installed immediately, so
104
+ posthog.capture()/opt_in_capturing() calls (e.g. from the cookie
105
+ banner) queue as before, but the ~130 KB library (array.js, then
106
+ config.js/surveys.js) is only fetched after the window `load` event
107
+ and the next idle period. It used to be inserted while the page was
108
+ still parsing and competed with first paint on mobile. The snippet is
109
+ PostHog's official one; the only change is that its insertBefore()
110
+ runs through __phInject. {% endcomment %}
111
+ window.__phInject = function (insert) {
112
+ var run = function () {
113
+ if (window.requestIdleCallback) window.requestIdleCallback(insert, { timeout: 3000 });
114
+ else setTimeout(insert, 1);
115
+ };
116
+ if (document.readyState === 'complete') run();
117
+ else window.addEventListener('load', run, { once: true });
118
+ };
103
119
  {% comment %} PostHog Loading Script {% endcomment %}
104
- !function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init Rr Mr fi Or Ar ci Tr Cr capture Mi calculateEventProperties Lr register register_once register_for_session unregister unregister_for_session Hr getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey canRenderSurvey canRenderSurveyAsync identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty Ur jr createPersonProfile zr kr Br opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing Dr debug M Nr getPageViewId captureTraceFeedback captureTraceMetric $r".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
120
+ !function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",window.__phInject(function(){(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r)});var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init Rr Mr fi Or Ar ci Tr Cr capture Mi calculateEventProperties Lr register register_once register_for_session unregister unregister_for_session Hr getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey canRenderSurvey canRenderSurveyAsync identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty Ur jr createPersonProfile zr kr Br opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing Dr debug M Nr getPageViewId captureTraceFeedback captureTraceMetric $r".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
105
121
 
106
122
  {% comment %} Initialize PostHog with configuration {% endcomment %}
107
123
  posthog.init(window.posthogConfig.apiKey, {
@@ -129,14 +145,17 @@ Privacy: Respects Do Not Track and provides opt-out mechanisms
129
145
  posthog.register({ '$geoip_disable': true });
130
146
  }
131
147
 
132
- {% comment %} Track Jekyll-specific page properties {% endcomment %}
148
+ {% comment %} Track Jekyll-specific page properties. Free-text values go
149
+ through `jsonify`: they used to be pasted between single quotes, so
150
+ an apostrophe in a title or description ("you're") was a
151
+ SyntaxError that stopped PostHog loading at all. {% endcomment %}
133
152
  posthog.register({
134
- 'site_title': '{{ site.title }}',
135
- 'site_description': '{{ site.description | strip_newlines | strip }}',
153
+ 'site_title': {{ site.title | jsonify }},
154
+ 'site_description': {{ site.description | strip_newlines | strip | jsonify }},
136
155
  'jekyll_version': '{{ jekyll.version }}',
137
- 'theme': '{{ site.remote_theme | default: site.theme }}',
138
- 'page_layout': '{{ page.layout }}',
139
- 'page_collection': '{{ page.collection }}',
156
+ 'theme': {{ site.remote_theme | default: site.theme | jsonify }},
157
+ 'page_layout': {{ page.layout | jsonify }},
158
+ 'page_collection': {{ page.collection | jsonify }},
140
159
  {% if page.categories %}
141
160
  'page_categories': {{ page.categories | jsonify }},
142
161
  {% endif %}
@@ -144,8 +163,8 @@ Privacy: Respects Do Not Track and provides opt-out mechanisms
144
163
  'page_tags': {{ page.tags | jsonify }},
145
164
  {% endif %}
146
165
  'page_url': window.location.pathname,
147
- 'page_title': '{{ page.title | strip_newlines | strip }}',
148
- 'page_author': '{{ page.author | default: site.author.name }}',
166
+ 'page_title': {{ page.title | strip_newlines | strip | jsonify }},
167
+ 'page_author': {{ page.author | default: site.author.name | jsonify }},
149
168
  {% if page.date %}
150
169
  'page_date': '{{ page.date | date: "%Y-%m-%d" }}',
151
170
  {% endif %}
@@ -79,7 +79,7 @@ If a component needs a token that doesn't exist yet, propose it in `_sass/tokens
79
79
  | `callout.html` | Highlighted info/note/warning/tip block, à la Bootstrap docs. |
80
80
  | `cta-button.html` | Themed call-to-action button with icon support. |
81
81
  | `feature-card.html` | Renders a single entry from `_data/features.yml`. |
82
- | `preview-image.html` | Lazy-loaded responsive image with assets-prefix handling. |
82
+ | `preview-image.html` | Responsive image with assets-prefix handling; lazy by default, optional `loading`/`fetchpriority`/`decoding` (pass `loading="eager" fetchpriority="high"` for an above-the-fold hero). |
83
83
  | `post-type-badge.html` | Visual badge for post types (featured, opinion, …). |
84
84
 
85
85
  ### Site chrome (rendered by layouts, not authors)
@@ -80,7 +80,13 @@
80
80
  {%- endif -%}
81
81
  {%- endif -%}
82
82
 
83
- {%- comment -%} Path resolution -- see preview-image.html {%- endcomment -%}
83
+ {%- comment -%} Path resolution -- see preview-image.html (including the
84
+ leading-slash normalisation: "images/x.png" must not become
85
+ "/assetsimages/x.png"). {%- endcomment -%}
86
+ {%- unless bgi_src == nil or bgi_src == "" or bgi_src contains '://' or bgi_src contains 'data:' -%}
87
+ {%- assign bgi_first = bgi_src | slice: 0 -%}
88
+ {%- if bgi_first != '/' -%}{%- assign bgi_src = '/' | append: bgi_src -%}{%- endif -%}
89
+ {%- endunless -%}
84
90
  {%- assign bgi_assets_prefix = site.preview_images.assets_prefix | default: '/assets' -%}
85
91
  {%- assign bgi_auto_prefix = site.preview_images.auto_prefix | default: true -%}
86
92
  {%- if bgi_src == nil or bgi_src == "" -%}
@@ -50,36 +50,36 @@ Usage: Include in root.html layout
50
50
  Configuration: Uses site.posthog settings from _config.yml
51
51
  {% endcomment %}
52
52
 
53
- <div id="cookieConsent" class="cookie-consent-banner position-fixed bottom-0 start-0 end-0 py-3 px-3 shadow-lg" hidden>
54
- <div class="container-xl px-3 px-md-4">
55
- <div class="row align-items-center g-2">
56
- <div class="col-12 col-lg-8">
57
- <p class="h6 fw-semibold mb-2 mb-lg-0">
58
- <i class="bi bi-shield-check me-2" aria-hidden="true"></i>
59
- We value your privacy
60
- </p>
61
- <p class="mb-2 mb-lg-0 small text-body-secondary">
62
- This website uses cookies and similar technologies to enhance your browsing experience, analyze traffic, and provide personalized content.
63
- {% assign cookie_page_urls = site.html_pages | map: "url" | join: "|" | prepend: "|" | append: "|" %}
64
- {% if site.privacy_policy_url or cookie_page_urls contains "|/privacy-policy/|" or cookie_page_urls contains "|/privacy-policy|" %}
65
- <a href="{{ site.privacy_policy_url | default: '/privacy-policy/' | relative_url }}" class="link-body-emphasis text-decoration-underline">Learn more in our Privacy Policy</a>.
66
- {% endif %}
67
- </p>
68
- </div>
69
- <div class="col-12 col-lg-4">
70
- <div class="d-flex flex-wrap gap-2 justify-content-lg-end">
71
- <button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#cookieSettingsModal">
72
- <i class="bi bi-gear me-1"></i>
73
- Manage Cookies
74
- </button>
75
- <button type="button" class="btn btn-sm btn-secondary" id="rejectAllCookies">
76
- Reject All
77
- </button>
78
- <button type="button" class="btn btn-sm btn-primary" id="acceptAllCookies">
79
- Accept All
80
- </button>
81
- </div>
82
- </div>
53
+ {% comment %}
54
+ Compact bottom bar. One row from md up (copy left, actions right); on phones
55
+ a two-line summary over a single row of three equal buttons. The banner used
56
+ to stack full-width buttons under a heading and a long sentence: 324px tall
57
+ at 400px wide (most of the first screen) and 94px on desktop, covering hero
58
+ copy. The per-category detail lives in the Manage modal.
59
+ {% endcomment %}
60
+ <div id="cookieConsent" class="cookie-consent-banner position-fixed bottom-0 start-0 end-0 shadow-lg" role="region" aria-label="Cookie consent" hidden>
61
+ <div class="container-xl cookie-consent-banner__inner">
62
+ <p class="cookie-consent-banner__text small mb-0">
63
+ <i class="bi bi-shield-check me-1" aria-hidden="true"></i>
64
+ <strong class="fw-semibold">We value your privacy.</strong>
65
+ <span class="text-body-secondary">
66
+ We use cookies to analyze traffic and improve the site.
67
+ {% assign cookie_page_urls = site.html_pages | map: "url" | join: "|" | prepend: "|" | append: "|" %}
68
+ {% if site.privacy_policy_url or cookie_page_urls contains "|/privacy-policy/|" or cookie_page_urls contains "|/privacy-policy|" %}
69
+ <a href="{{ site.privacy_policy_url | default: '/privacy-policy/' | relative_url }}" class="link-body-emphasis text-decoration-underline">Privacy Policy</a>
70
+ {% endif %}
71
+ </span>
72
+ </p>
73
+ <div class="cookie-consent-banner__actions">
74
+ <button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#cookieSettingsModal">
75
+ <i class="bi bi-gear me-1" aria-hidden="true"></i>Manage<span class="d-none d-sm-inline"> Cookies</span>
76
+ </button>
77
+ <button type="button" class="btn btn-sm btn-secondary" id="rejectAllCookies">
78
+ Reject All
79
+ </button>
80
+ <button type="button" class="btn btn-sm btn-primary" id="acceptAllCookies">
81
+ Accept All
82
+ </button>
83
83
  </div>
84
84
  </div>
85
85
  </div>
@@ -4,7 +4,7 @@
4
4
  Path: _includes/components/mermaid.html
5
5
  Purpose: Load Mermaid and the theme's diagram-figure behaviour on pages
6
6
  that opt in with `mermaid: true` (gated in core/head.html).
7
- Emits a config block and two deferred scripts; renders no
7
+ Emits a config block and one deferred script; renders no
8
8
  markup itself — every ```mermaid fence (and legacy
9
9
  <div class="mermaid">) becomes an accessible <figure> with a
10
10
  toolbar (zoom, fullscreen, copy source, download SVG), a
@@ -22,11 +22,15 @@
22
22
  Depends on: assets/vendor/mermaid/mermaid.min.js (vendored, no CDN —
23
23
  GitHub Pages-safe), assets/js/mermaid-diagrams.js,
24
24
  _sass/components/_mermaid.scss
25
- Notes: Both scripts are `defer`: Mermaid is a 3.3 MB bundle and must
26
- never block parsing (it used to load synchronously in <head>).
27
- Order matters — the vendor bundle first, then the behaviour,
28
- which converts fences at execution time, before code-copy.js's
29
- DOMContentLoaded pass decorates <pre> blocks. Diagram colours
25
+ Notes: The Mermaid bundle (~1 MB) is NOT emitted as a <script> any
26
+ more. mermaid-diagrams.js (deferred) converts fences into
27
+ figures at execution time, before code-copy.js's
28
+ DOMContentLoaded pass decorates <pre> blocks, and injects the
29
+ bundle from `src` below only when the page has a diagram and
30
+ the first one nears the viewport (IntersectionObserver). A
31
+ `mermaid: true` page without fences never downloads it. It used
32
+ to be a parse-time `defer` script on every opted-in page, and
33
+ before that a synchronous one in <head>. Diagram colours
30
34
  are not configured here: the script derives them from the live
31
35
  --zer0-*/--bs-* tokens so light/dark/wizard modes and skins
32
36
  work without per-mode overrides.
@@ -71,5 +75,8 @@
71
75
  }
72
76
  }
73
77
  </script>
74
- <script defer src="{{ mm_src | relative_url }}"></script>
78
+ {% comment %} Bundle URL for the lazy loader. Passed as a script global rather than
79
+ through the JSON block above: a URL read back out of DOM text and assigned
80
+ to script.src is a script-injection sink (CodeQL js/xss-through-dom). {% endcomment %}
81
+ <script>window.zer0MermaidSrc = {{ mm_src | relative_url | jsonify }};</script>
75
82
  <script defer src="{{ '/assets/js/mermaid-diagrams.js' | relative_url }}"></script>
@@ -7,9 +7,18 @@
7
7
  src=post.preview
8
8
  alt=post.title
9
9
  class="card-img-top"
10
- style="height: 180px; object-fit: cover;"
10
+ style="height: 180px; object-fit: cover;"
11
11
  -%}
12
-
12
+
13
+ Optional: loading (default "lazy"), fetchpriority, decoding, width, height.
14
+ All but `loading` are emitted only when passed, so existing call sites
15
+ render unchanged. width/height are the image's intrinsic size (or its
16
+ aspect ratio): they let the browser reserve the box before the file
17
+ arrives (Lighthouse `unsized-images`) and never distort the image, since
18
+ CSS height:auto / object-fit still win once it has loaded.
19
+ An above-the-fold hero (the LCP element) should pass loading="eager"
20
+ fetchpriority="high" -- see the article.html hero.
21
+
13
22
  WHICH INCLUDE: this one renders an <img> in the content flow. For cover art
14
23
  painted as a CSS background on an otherwise empty box, use the sibling
15
24
  components/background-image.html -- a background image is invisible to
@@ -20,6 +29,8 @@
20
29
  The component will auto-prepend the assets_prefix from _config.yml.
21
30
  Examples:
22
31
  - /images/previews/my-image.png → /assets/images/previews/my-image.png
32
+ - images/previews/my-image.png → /assets/images/previews/my-image.png
33
+ (a missing leading slash used to produce /assetsimages/previews/…)
23
34
  - /assets/images/previews/my-image.png → unchanged
24
35
  - https://example.com/image.png → unchanged (external URL)
25
36
  {% endcomment %}
@@ -33,6 +44,14 @@
33
44
  {% assign assets_prefix = site.preview_images.assets_prefix | default: '/assets' %}
34
45
  {% assign auto_prefix = site.preview_images.auto_prefix | default: true %}
35
46
 
47
+ {% comment %} Normalise a site-relative path to start with "/" so joining it to
48
+ assets_prefix can never glue two segments together ("images/x.png" became
49
+ "/assetsimages/x.png"). URLs and data: URIs are left alone. {% endcomment %}
50
+ {% unless img == nil or img == "" or img contains '://' or img contains 'data:' %}
51
+ {% assign img_first = img | slice: 0 %}
52
+ {% if img_first != '/' %}{% assign img = '/' | append: img %}{% endif %}
53
+ {% endunless %}
54
+
36
55
  {% comment %} Determine final image source {% endcomment %}
37
56
  {% if img contains '://' %}
38
57
  {% comment %} External URL - use as-is {% endcomment %}
@@ -53,4 +72,4 @@
53
72
  class="{{ class }}"
54
73
  alt="{{ alt | escape }}"
55
74
  {% if style %}style="{{ style }}"{% endif %}
56
- loading="{{ loading }}">
75
+ loading="{{ loading }}"{% if include.width %} width="{{ include.width }}"{% endif %}{% if include.height %} height="{{ include.height }}"{% endif %}{% if include.fetchpriority %} fetchpriority="{{ include.fetchpriority }}"{% endif %}{% if include.decoding %} decoding="{{ include.decoding }}"{% endif %}>
@@ -519,7 +519,7 @@ docker-compose up
519
519
  <i class="bi bi-person-circle" title="bi-person-circle"></i>
520
520
  <i class="bi bi-palette" title="bi-palette"></i>
521
521
  <i class="bi bi-code-slash" title="bi-code-slash"></i>
522
- <i class="bi bi-file-earmark-text"title="bi-file-earmark-text"></i>
522
+ <i class="bi bi-file-earmark-text" title="bi-file-earmark-text"></i>
523
523
  <i class="bi bi-check-circle text-success" title="success"></i>
524
524
  <i class="bi bi-x-circle text-danger" title="danger"></i>
525
525
  <i class="bi bi-exclamation-triangle text-warning" title="warning"></i>
@@ -29,6 +29,13 @@
29
29
  {% assign assets_prefix = site.preview_images.assets_prefix | default: '/assets' %}
30
30
  {% assign auto_prefix = site.preview_images.auto_prefix | default: true %}
31
31
 
32
+ {% comment %} Leading-slash normalisation, as in components/preview-image.html:
33
+ `preview: images/x.png` used to resolve to /assetsimages/x.png. {% endcomment %}
34
+ {% unless preview_image == nil or preview_image == "" or preview_image contains '://' or preview_image contains 'data:' %}
35
+ {% assign preview_first = preview_image | slice: 0 %}
36
+ {% if preview_first != '/' %}{% assign preview_image = '/' | append: preview_image %}{% endif %}
37
+ {% endunless %}
38
+
32
39
  {% if preview_image contains '://' %}
33
40
  {% assign preview_path = preview_image %}
34
41
  {% elsif auto_prefix and preview_image != blank %}
@@ -43,6 +43,14 @@
43
43
  nil seo_image — og:image was silently dropped on every page without a
44
44
  page.header image, defeating the site.og_image fallback entirely.
45
45
  {%- endcomment -%}
46
+ {%- comment -%} Leading-slash normalisation, as in components/preview-image.html:
47
+ `preview: images/x.png` used to become og:image …/assetsimages/x.png. {%- endcomment -%}
48
+ {%- if page_teaser_image and page_teaser_image != "" -%}
49
+ {%- unless page_teaser_image contains '://' or page_teaser_image contains 'data:' -%}
50
+ {%- assign teaser_first = page_teaser_image | slice: 0 -%}
51
+ {%- if teaser_first != '/' -%}{%- assign page_teaser_image = '/' | append: page_teaser_image -%}{%- endif -%}
52
+ {%- endunless -%}
53
+ {%- endif -%}
46
54
  {%- if page_teaser_image contains '://' -%}
47
55
  {%- comment -%} External URL - use as-is {%- endcomment -%}
48
56
  {%- elsif auto_prefix and page_teaser_image and page_teaser_image != blank -%}