jekyll-theme-zer0 1.29.0 → 1.30.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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +715 -2
  3. data/_data/README.md +2 -0
  4. data/_data/ai.yml +5 -3
  5. data/_data/ai_pricing.yml +36 -0
  6. data/_data/backlog.yml +169 -18
  7. data/_data/consumers.yml +48 -5
  8. data/_data/features.yml +146 -20
  9. data/_data/feedback_types.yml +17 -12
  10. data/_data/landing.yml +5 -2
  11. data/_data/navigation/quickstart.yml +4 -0
  12. data/_data/site_builder.yml +874 -0
  13. data/_data/theme-manifest.yml +122 -114
  14. data/_data/ui-text.yml +18 -0
  15. data/_includes/README.md +11 -1
  16. data/_includes/analytics/posthog.html +2 -2
  17. data/_includes/components/admin-links.html +2 -2
  18. data/_includes/components/admin-tabs.html +2 -2
  19. data/_includes/components/ai-chat.html +14 -11
  20. data/_includes/components/analytics-dashboard.html +8 -8
  21. data/_includes/components/author-bio.html +1 -1
  22. data/_includes/components/author-card.html +10 -2
  23. data/_includes/components/author-eeat.html +4 -4
  24. data/_includes/components/background-customizer.html +8 -8
  25. data/_includes/components/background-image.html +114 -0
  26. data/_includes/components/background-settings.html +28 -15
  27. data/_includes/components/collection-manager.html +5 -5
  28. data/_includes/components/component-showcase.html +13 -13
  29. data/_includes/components/config-editor.html +12 -12
  30. data/_includes/components/config-viewer.html +8 -8
  31. data/_includes/components/cookie-consent.html +11 -11
  32. data/_includes/components/cta-button.html +7 -2
  33. data/_includes/components/dev-shortcuts.html +7 -7
  34. data/_includes/components/env-dashboard.html +8 -8
  35. data/_includes/components/env-switcher.html +9 -9
  36. data/_includes/components/feature-card.html +2 -2
  37. data/_includes/components/halfmoon.html +2 -2
  38. data/_includes/components/info-section.html +36 -36
  39. data/_includes/components/js-cdn.html +15 -15
  40. data/_includes/components/language-toggle.html +4 -4
  41. data/_includes/components/mermaid.html +72 -435
  42. data/_includes/components/nanobar.html +5 -5
  43. data/_includes/components/nav-editor.html +2 -2
  44. data/_includes/components/nav-export.html +2 -2
  45. data/_includes/components/nav-overview.html +2 -2
  46. data/_includes/components/page-feedback.html +45 -30
  47. data/_includes/components/page-views-init.html +1 -1
  48. data/_includes/components/post-card.html +22 -22
  49. data/_includes/components/post-type-badge.html +2 -2
  50. data/_includes/components/powered-by.html +2 -2
  51. data/_includes/components/preview-image.html +6 -0
  52. data/_includes/components/quick-index.html +2 -2
  53. data/_includes/components/search-modal.html +27 -2
  54. data/_includes/components/searchbar.html +2 -2
  55. data/_includes/components/svg-background.html +2 -2
  56. data/_includes/components/theme-customizer.html +2 -2
  57. data/_includes/components/theme-info.html +6 -6
  58. data/_includes/components/theme-preview-gallery.html +22 -22
  59. data/_includes/content/giscus.html +2 -2
  60. data/_includes/content/intro.html +8 -8
  61. data/_includes/content/jsonld-faq.html +2 -2
  62. data/_includes/content/jsonld-software.html +2 -2
  63. data/_includes/content/seo.html +4 -4
  64. data/_includes/content/sitemap.html +27 -27
  65. data/_includes/content/toc.html +183 -183
  66. data/_includes/core/branding.html +6 -6
  67. data/_includes/core/console-capture.html +32 -74
  68. data/_includes/core/favicon.html +49 -7
  69. data/_includes/core/footer-fabs.html +17 -3
  70. data/_includes/core/footer.html +31 -18
  71. data/_includes/core/head.html +102 -90
  72. data/_includes/core/header.html +71 -52
  73. data/_includes/docs/bootstrap-docs.html +8 -8
  74. data/_includes/landing/landing-install-cards.html +2 -2
  75. data/_includes/landing/landing-quick-links.html +1 -1
  76. data/_includes/navigation/admin-nav.html +2 -2
  77. data/_includes/navigation/nav-tree.html +8 -8
  78. data/_includes/navigation/navbar.html +12 -12
  79. data/_includes/navigation/section-sidebar.html +16 -16
  80. data/_includes/navigation/sidebar-config.html +36 -2
  81. data/_includes/navigation/sidebar-left.html +15 -15
  82. data/_includes/navigation/sidebar-right.html +6 -6
  83. data/_includes/obsidian/full-graph.html +2 -2
  84. data/_includes/setup/claude-session.html +72 -0
  85. data/_includes/setup/prereq-checklist.html +90 -0
  86. data/_includes/setup/wizard.html +906 -291
  87. data/_includes/stats/stats-categories.html +8 -8
  88. data/_includes/stats/stats-header.html +14 -14
  89. data/_includes/stats/stats-metrics.html +12 -12
  90. data/_includes/stats/stats-no-data.html +12 -12
  91. data/_includes/stats/stats-overview.html +6 -6
  92. data/_includes/stats/stats-tags.html +8 -8
  93. data/_layouts/404.html +38 -24
  94. data/_layouts/admin.html +22 -22
  95. data/_layouts/article.html +39 -34
  96. data/_layouts/author.html +20 -20
  97. data/_layouts/authors.html +2 -2
  98. data/_layouts/book-abc.html +12 -12
  99. data/_layouts/book-story.html +15 -15
  100. data/_layouts/book.html +12 -12
  101. data/_layouts/collection.html +33 -33
  102. data/_layouts/cookbook.html +12 -12
  103. data/_layouts/default.html +27 -24
  104. data/_layouts/home.html +23 -23
  105. data/_layouts/index.html +10 -10
  106. data/_layouts/landing.html +17 -17
  107. data/_layouts/news.html +44 -44
  108. data/_layouts/note.html +38 -38
  109. data/_layouts/notebook.html +34 -34
  110. data/_layouts/recipe.html +24 -24
  111. data/_layouts/root.html +73 -55
  112. data/_layouts/section.html +23 -23
  113. data/_layouts/setup.html +3 -3
  114. data/_layouts/sitemap-collection.html +49 -49
  115. data/_layouts/stats.html +40 -40
  116. data/_layouts/tag.html +12 -12
  117. data/_layouts/welcome.html +21 -21
  118. data/_sass/components/_mermaid.scss +375 -0
  119. data/_sass/components/_setup-wizard.scss +569 -40
  120. data/_sass/core/_navbar.scss +11 -31
  121. data/_sass/layouts/_navbar-extras.scss +14 -4
  122. data/assets/css/main.scss +1 -0
  123. data/assets/js/ai-chat.js +47 -5
  124. data/assets/js/fleet-feedback-capture.js +124 -0
  125. data/assets/js/fleet-feedback.js +853 -0
  126. data/assets/js/mermaid-diagrams.js +1267 -0
  127. data/assets/js/modules/navigation/config.js +9 -6
  128. data/assets/js/modules/navigation/scroll-spy.js +315 -80
  129. data/assets/js/modules/theme/appearance.js +8 -2
  130. data/assets/js/obsidian-wiki-links.js +8 -3
  131. data/assets/js/page-feedback.js +125 -192
  132. data/assets/js/search-modal.js +26 -0
  133. data/assets/js/setup-wizard.js +2112 -361
  134. data/assets/js/site-builder.js +1834 -0
  135. data/assets/js/ui-enhancements.js +11 -3
  136. data/scripts/README.md +15 -0
  137. data/scripts/ai/README.md +38 -0
  138. data/scripts/ai/api_call.rb +124 -0
  139. data/scripts/ai/usage.rb +314 -0
  140. data/scripts/ai/usage_report.rb +225 -0
  141. data/scripts/ci/test_visual_evidence_autogen.py +341 -0
  142. data/scripts/ci/visual_evidence_autogen.py +1060 -0
  143. data/scripts/content-review.rb +20 -1
  144. data/scripts/test/integration/mermaid +22 -8
  145. data/scripts/test/lib/run_tests.sh +1 -0
  146. data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
  147. data/scripts/translate.rb +23 -1
  148. metadata +19 -2
@@ -1,183 +1,183 @@
1
- {% comment %} Feature: ZER0-037 {% endcomment %}
2
- {% capture tocWorkspace %}
3
- {% comment %}
4
- Copyright (c) 2017 Vladimir "allejo" Jimenez
5
-
6
- Permission is hereby granted, free of charge, to any person
7
- obtaining a copy of this software and associated documentation
8
- files (the "Software"), to deal in the Software without
9
- restriction, including without limitation the rights to use,
10
- copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- copies of the Software, and to permit persons to whom the
12
- Software is furnished to do so, subject to the following
13
- conditions:
14
-
15
- The above copyright notice and this permission notice shall be
16
- included in all copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
- OTHER DEALINGS IN THE SOFTWARE.
26
- {% endcomment %}
27
- {% comment %}
28
- Version 1.1.0
29
- https://github.com/allejo/jekyll-toc
30
-
31
- "...like all things liquid - where there's a will, and ~36 hours to spare, there's usually a/some way" ~jaybe
32
-
33
- Usage:
34
- {% include content/toc.html html=content sanitize=true class="inline_toc" id="my_toc" h_min=2 h_max=3 %}
35
-
36
- Parameters:
37
- * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
38
-
39
- Optional Parameters:
40
- * sanitize (bool) : false - when set to true, the headers will be stripped of any HTML in the TOC
41
- * class (string) : '' - a CSS class assigned to the TOC
42
- * id (string) : '' - an ID to assigned to the TOC
43
- * h_min (int) : 1 - the minimum TOC header level to use; any header lower than this value will be ignored
44
- * h_max (int) : 6 - the maximum TOC header level to use; any header greater than this value will be ignored
45
- * ordered (bool) : false - when set to true, an ordered list will be outputted instead of an unordered list
46
- * item_class (string) : '' - add custom class(es) for each list item; has support for '%level%' placeholder, which is the current heading level
47
- * submenu_class (string) : '' - add custom class(es) for each child group of headings; has support for '%level%' placeholder which is the current "submenu" heading level
48
- * base_url (string) : '' - add a base url to the TOC links for when your TOC is on another page than the actual content
49
- * anchor_class (string) : '' - add custom class(es) for each anchor element
50
- * skip_no_ids (bool) : false - skip headers that do not have an `id` attribute
51
-
52
- Output:
53
- An ordered or unordered list representing the table of contents of a markdown block. This snippet will only
54
- generate the table of contents and will NOT output the markdown given to it
55
- {% endcomment %}
56
-
57
- {% capture newline %}
58
- {% endcapture %}
59
- {% assign newline = newline | rstrip %} <!-- Remove the extra spacing but preserve the newline -->
60
-
61
- {% capture deprecation_warnings %}{% endcapture %}
62
-
63
- {% if include.baseurl %}
64
- {% capture deprecation_warnings %}{{ deprecation_warnings }}<!-- jekyll-toc :: "baseurl" has been deprecated, use "base_url" instead -->{{ newline }}{% endcapture %}
65
- {% endif %}
66
-
67
- {% if include.skipNoIDs %}
68
- {% capture deprecation_warnings %}{{ deprecation_warnings }}<!-- jekyll-toc :: "skipNoIDs" has been deprecated, use "skip_no_ids" instead -->{{ newline }}{% endcapture %}
69
- {% endif %}
70
-
71
- {% capture jekyll_toc %}{% endcapture %}
72
- {% assign orderedList = include.ordered | default: false %}
73
- {% assign baseURL = include.base_url | default: include.baseurl | default: '' %}
74
- {% assign skipNoIDs = include.skip_no_ids | default: include.skipNoIDs | default: false %}
75
- {% assign minHeader = include.h_min | default: 1 %}
76
- {% assign maxHeader = include.h_max | default: 6 %}
77
- {% assign nodes = include.html | strip | split: '<h' %}
78
-
79
- {% assign firstHeader = true %}
80
- {% assign currLevel = 0 %}
81
- {% assign lastLevel = 0 %}
82
-
83
- {% capture listModifier %}{% if orderedList %}ol{% else %}ul{% endif %}{% endcapture %}
84
-
85
- {% for node in nodes %}
86
- {% if node == "" %}
87
- {% continue %}
88
- {% endif %}
89
-
90
- {% assign currLevel = node | replace: '"', '' | slice: 0, 1 | times: 1 %}
91
-
92
- {% if currLevel < minHeader or currLevel > maxHeader %}
93
- {% continue %}
94
- {% endif %}
95
-
96
- {% assign _workspace = node | split: '</h' %}
97
-
98
- {% assign _idWorkspace = _workspace[0] | split: 'id="' %}
99
- {% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
100
- {% assign htmlID = _idWorkspace[0] %}
101
-
102
- {% assign _classWorkspace = _workspace[0] | split: 'class="' %}
103
- {% assign _classWorkspace = _classWorkspace[1] | split: '"' %}
104
- {% assign htmlClass = _classWorkspace[0] %}
105
-
106
- {% if htmlClass contains "no_toc" %}
107
- {% continue %}
108
- {% endif %}
109
-
110
- {% if firstHeader %}
111
- {% assign minHeader = currLevel %}
112
- {% endif %}
113
-
114
- {% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
115
- {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
116
-
117
- {% if include.item_class and include.item_class != blank %}
118
- {% capture listItemClass %} class="{{ include.item_class | replace: '%level%', currLevel | split: '.' | join: ' ' }}"{% endcapture %}
119
- {% endif %}
120
-
121
- {% if include.submenu_class and include.submenu_class != blank %}
122
- {% assign subMenuLevel = currLevel | minus: 1 %}
123
- {% capture subMenuClass %} class="{{ include.submenu_class | replace: '%level%', subMenuLevel | split: '.' | join: ' ' }}"{% endcapture %}
124
- {% endif %}
125
-
126
- {% capture anchorBody %}{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}{% endcapture %}
127
-
128
- {% if htmlID %}
129
- {% capture anchorAttributes %} href="{% if baseURL %}{{ baseURL }}{% endif %}#{{ htmlID }}"{% endcapture %}
130
-
131
- {% if include.anchor_class %}
132
- {% capture anchorAttributes %}{{ anchorAttributes }} class="{{ include.anchor_class | split: '.' | join: ' ' }}"{% endcapture %}
133
- {% endif %}
134
-
135
- {% capture listItem %}<a{{ anchorAttributes }}>{{ anchorBody }}</a>{% endcapture %}
136
- {% elsif skipNoIDs == true %}
137
- {% continue %}
138
- {% else %}
139
- {% capture listItem %}{{ anchorBody }}{% endcapture %}
140
- {% endif %}
141
-
142
- {% if currLevel > lastLevel %}
143
- {% capture jekyll_toc %}{{ jekyll_toc }}<{{ listModifier }}{{ subMenuClass }}>{% endcapture %}
144
- {% elsif currLevel < lastLevel %}
145
- {% assign repeatCount = lastLevel | minus: currLevel %}
146
-
147
- {% for i in (1..repeatCount) %}
148
- {% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
149
- {% endfor %}
150
-
151
- {% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
152
- {% else %}
153
- {% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
154
- {% endif %}
155
-
156
- {% capture jekyll_toc %}{{ jekyll_toc }}<li{{ listItemClass }}>{{ listItem }}{% endcapture %}
157
-
158
- {% assign lastLevel = currLevel %}
159
- {% assign firstHeader = false %}
160
- {% endfor %}
161
-
162
- {% assign repeatCount = minHeader | minus: 1 %}
163
- {% assign repeatCount = lastLevel | minus: repeatCount %}
164
- {% for i in (1..repeatCount) %}
165
- {% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
166
- {% endfor %}
167
-
168
- {% if jekyll_toc != '' %}
169
- {% assign rootAttributes = '' %}
170
- {% if include.class and include.class != blank %}
171
- {% capture rootAttributes %} class="{{ include.class | split: '.' | join: ' ' }}"{% endcapture %}
172
- {% endif %}
173
-
174
- {% if include.id and include.id != blank %}
175
- {% capture rootAttributes %}{{ rootAttributes }} id="{{ include.id }}"{% endcapture %}
176
- {% endif %}
177
-
178
- {% if rootAttributes %}
179
- {% assign nodes = jekyll_toc | split: '>' %}
180
- {% capture jekyll_toc %}<{{ listModifier }}{{ rootAttributes }}>{{ nodes | shift | join: '>' }}>{% endcapture %}
181
- {% endif %}
182
- {% endif %}
183
- {% endcapture %}{% assign tocWorkspace = '' %}{{ deprecation_warnings }}{{ jekyll_toc }}
1
+ {% comment %} Feature: ZER0-037 {% endcomment %}
2
+ {% capture tocWorkspace %}
3
+ {% comment %}
4
+ Copyright (c) 2017 Vladimir "allejo" Jimenez
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the "Software"), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
26
+ {% endcomment %}
27
+ {% comment %}
28
+ Version 1.1.0
29
+ https://github.com/allejo/jekyll-toc
30
+
31
+ "...like all things liquid - where there's a will, and ~36 hours to spare, there's usually a/some way" ~jaybe
32
+
33
+ Usage:
34
+ {% include content/toc.html html=content sanitize=true class="inline_toc" id="my_toc" h_min=2 h_max=3 %}
35
+
36
+ Parameters:
37
+ * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
38
+
39
+ Optional Parameters:
40
+ * sanitize (bool) : false - when set to true, the headers will be stripped of any HTML in the TOC
41
+ * class (string) : '' - a CSS class assigned to the TOC
42
+ * id (string) : '' - an ID to assigned to the TOC
43
+ * h_min (int) : 1 - the minimum TOC header level to use; any header lower than this value will be ignored
44
+ * h_max (int) : 6 - the maximum TOC header level to use; any header greater than this value will be ignored
45
+ * ordered (bool) : false - when set to true, an ordered list will be outputted instead of an unordered list
46
+ * item_class (string) : '' - add custom class(es) for each list item; has support for '%level%' placeholder, which is the current heading level
47
+ * submenu_class (string) : '' - add custom class(es) for each child group of headings; has support for '%level%' placeholder which is the current "submenu" heading level
48
+ * base_url (string) : '' - add a base url to the TOC links for when your TOC is on another page than the actual content
49
+ * anchor_class (string) : '' - add custom class(es) for each anchor element
50
+ * skip_no_ids (bool) : false - skip headers that do not have an `id` attribute
51
+
52
+ Output:
53
+ An ordered or unordered list representing the table of contents of a markdown block. This snippet will only
54
+ generate the table of contents and will NOT output the markdown given to it
55
+ {% endcomment %}
56
+
57
+ {% capture newline %}
58
+ {% endcapture %}
59
+ {% assign newline = newline | rstrip %} {% comment %} Remove the extra spacing but preserve the newline {% endcomment %}
60
+
61
+ {% capture deprecation_warnings %}{% endcapture %}
62
+
63
+ {% if include.baseurl %}
64
+ {% capture deprecation_warnings %}{{ deprecation_warnings }}{% comment %} jekyll-toc :: "baseurl" has been deprecated, use "base_url" instead {% endcomment %}{{ newline }}{% endcapture %}
65
+ {% endif %}
66
+
67
+ {% if include.skipNoIDs %}
68
+ {% capture deprecation_warnings %}{{ deprecation_warnings }}{% comment %} jekyll-toc :: "skipNoIDs" has been deprecated, use "skip_no_ids" instead {% endcomment %}{{ newline }}{% endcapture %}
69
+ {% endif %}
70
+
71
+ {% capture jekyll_toc %}{% endcapture %}
72
+ {% assign orderedList = include.ordered | default: false %}
73
+ {% assign baseURL = include.base_url | default: include.baseurl | default: '' %}
74
+ {% assign skipNoIDs = include.skip_no_ids | default: include.skipNoIDs | default: false %}
75
+ {% assign minHeader = include.h_min | default: 1 %}
76
+ {% assign maxHeader = include.h_max | default: 6 %}
77
+ {% assign nodes = include.html | strip | split: '<h' %}
78
+
79
+ {% assign firstHeader = true %}
80
+ {% assign currLevel = 0 %}
81
+ {% assign lastLevel = 0 %}
82
+
83
+ {% capture listModifier %}{% if orderedList %}ol{% else %}ul{% endif %}{% endcapture %}
84
+
85
+ {% for node in nodes %}
86
+ {% if node == "" %}
87
+ {% continue %}
88
+ {% endif %}
89
+
90
+ {% assign currLevel = node | replace: '"', '' | slice: 0, 1 | times: 1 %}
91
+
92
+ {% if currLevel < minHeader or currLevel > maxHeader %}
93
+ {% continue %}
94
+ {% endif %}
95
+
96
+ {% assign _workspace = node | split: '</h' %}
97
+
98
+ {% assign _idWorkspace = _workspace[0] | split: 'id="' %}
99
+ {% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
100
+ {% assign htmlID = _idWorkspace[0] %}
101
+
102
+ {% assign _classWorkspace = _workspace[0] | split: 'class="' %}
103
+ {% assign _classWorkspace = _classWorkspace[1] | split: '"' %}
104
+ {% assign htmlClass = _classWorkspace[0] %}
105
+
106
+ {% if htmlClass contains "no_toc" %}
107
+ {% continue %}
108
+ {% endif %}
109
+
110
+ {% if firstHeader %}
111
+ {% assign minHeader = currLevel %}
112
+ {% endif %}
113
+
114
+ {% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
115
+ {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
116
+
117
+ {% if include.item_class and include.item_class != blank %}
118
+ {% capture listItemClass %} class="{{ include.item_class | replace: '%level%', currLevel | split: '.' | join: ' ' }}"{% endcapture %}
119
+ {% endif %}
120
+
121
+ {% if include.submenu_class and include.submenu_class != blank %}
122
+ {% assign subMenuLevel = currLevel | minus: 1 %}
123
+ {% capture subMenuClass %} class="{{ include.submenu_class | replace: '%level%', subMenuLevel | split: '.' | join: ' ' }}"{% endcapture %}
124
+ {% endif %}
125
+
126
+ {% capture anchorBody %}{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}{% endcapture %}
127
+
128
+ {% if htmlID %}
129
+ {% capture anchorAttributes %} href="{% if baseURL %}{{ baseURL }}{% endif %}#{{ htmlID }}"{% endcapture %}
130
+
131
+ {% if include.anchor_class %}
132
+ {% capture anchorAttributes %}{{ anchorAttributes }} class="{{ include.anchor_class | split: '.' | join: ' ' }}"{% endcapture %}
133
+ {% endif %}
134
+
135
+ {% capture listItem %}<a{{ anchorAttributes }}>{{ anchorBody }}</a>{% endcapture %}
136
+ {% elsif skipNoIDs == true %}
137
+ {% continue %}
138
+ {% else %}
139
+ {% capture listItem %}{{ anchorBody }}{% endcapture %}
140
+ {% endif %}
141
+
142
+ {% if currLevel > lastLevel %}
143
+ {% capture jekyll_toc %}{{ jekyll_toc }}<{{ listModifier }}{{ subMenuClass }}>{% endcapture %}
144
+ {% elsif currLevel < lastLevel %}
145
+ {% assign repeatCount = lastLevel | minus: currLevel %}
146
+
147
+ {% for i in (1..repeatCount) %}
148
+ {% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
149
+ {% endfor %}
150
+
151
+ {% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
152
+ {% else %}
153
+ {% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
154
+ {% endif %}
155
+
156
+ {% capture jekyll_toc %}{{ jekyll_toc }}<li{{ listItemClass }}>{{ listItem }}{% endcapture %}
157
+
158
+ {% assign lastLevel = currLevel %}
159
+ {% assign firstHeader = false %}
160
+ {% endfor %}
161
+
162
+ {% assign repeatCount = minHeader | minus: 1 %}
163
+ {% assign repeatCount = lastLevel | minus: repeatCount %}
164
+ {% for i in (1..repeatCount) %}
165
+ {% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
166
+ {% endfor %}
167
+
168
+ {% if jekyll_toc != '' %}
169
+ {% assign rootAttributes = '' %}
170
+ {% if include.class and include.class != blank %}
171
+ {% capture rootAttributes %} class="{{ include.class | split: '.' | join: ' ' }}"{% endcapture %}
172
+ {% endif %}
173
+
174
+ {% if include.id and include.id != blank %}
175
+ {% capture rootAttributes %}{{ rootAttributes }} id="{{ include.id }}"{% endcapture %}
176
+ {% endif %}
177
+
178
+ {% if rootAttributes %}
179
+ {% assign nodes = jekyll_toc | split: '>' %}
180
+ {% capture jekyll_toc %}<{{ listModifier }}{{ rootAttributes }}>{{ nodes | shift | join: '>' }}>{% endcapture %}
181
+ {% endif %}
182
+ {% endif %}
183
+ {% endcapture %}{% assign tocWorkspace = '' %}{{ deprecation_warnings }}{{ jekyll_toc }}
@@ -1,4 +1,4 @@
1
- <!--
1
+ {% comment %}
2
2
  ===================================================================
3
3
  BRANDING - Site Title and Subtitle Display
4
4
  ===================================================================
@@ -14,8 +14,8 @@
14
14
  - site.title_icon: Icon for title display
15
15
  - site.subtitle_icon: Icon for subtitle display
16
16
  ===================================================================
17
- -->
18
- <!-- Color Schema Override
17
+ {% endcomment %}
18
+ {% comment %} Color Schema Override
19
19
  TODO: Add a poline plug-in to generate color scheme
20
20
  https://meodai.github.io/poline/
21
21
 
@@ -28,9 +28,9 @@
28
28
  Yellow - #ffe900
29
29
  Teal - #376986
30
30
  Blue - #007bff
31
- -->
31
+ {% endcomment %}
32
32
 
33
- <!-- Title Section -->
33
+ {% comment %} Title Section {% endcomment %}
34
34
 
35
35
  <div class="navbar-brand site-title mb-0 py-0 me-0 min-w-0 flex-grow-1">
36
36
  <a
@@ -43,7 +43,7 @@
43
43
  </a>
44
44
  </div>
45
45
 
46
- <!-- If a subtitle exists -->
46
+ {% comment %} If a subtitle exists {% endcomment %}
47
47
  {%- assign _subtitle = site.subtitle | strip -%}
48
48
  {%- if _subtitle != "" -%}
49
49
  <div class="navbar-brand site-subtitle d-none d-lg-inline">
@@ -1,89 +1,47 @@
1
1
  {%- comment -%}
2
2
  ===================================================================
3
- CONSOLE CAPTURE — early, tiny console/error ring buffer
3
+ CONSOLE CAPTURE — early console/error ring buffer
4
4
  ===================================================================
5
5
 
6
6
  File: console-capture.html
7
7
  Path: _includes/core/console-capture.html
8
- Purpose: Capture a capped, in-memory buffer of console output and
9
- uncaught errors, installed HIGH in <head> — before the
10
- theme's deferred scripts run — so the page-feedback widget
11
- (assets/js/page-feedback.js) can attach the logs and JS
12
- errors that led up to a report.
8
+ Purpose: Load the fleet feedback kit's capture buffer HIGH in <head> —
9
+ before the theme's deferred scripts run — so the page-feedback
10
+ widget can attach the logs and JS errors that led up to a report.
13
11
 
14
12
  Renders: only when page_feedback.enabled AND page_feedback.capture_logs.
15
13
 
14
+ This used to be ~60 lines of inline ES5 maintained here. It is now the
15
+ fleet kit's capture.js, VENDORED to assets/js/fleet-feedback-capture.js
16
+ (bamr87/bamr87 templates/feedback/capture.js — drift check (i) holds the
17
+ copy to the hub's). Two things came with the move: the buffer shape is
18
+ now the one FleetFeedbackCore reads, so the theme's widget and the fleet's
19
+ web component file byte-identical issues; and every captured line is
20
+ REDACTED before it enters the ring (bearer/API keys, JWTs, GitHub tokens,
21
+ email addresses), so a secret cannot be previewed, copied, or filed.
22
+
23
+ Loaded blocking rather than deferred, and that is the point: a buffer
24
+ installed after parsing misses exactly the load-time failures worth
25
+ reporting. It is ~4 KB, and it REPLACED ~3.7 KB of inline script, so the
26
+ head got smaller — which also buys back room for the charset meta that
27
+ has to land in the first 1024 bytes (issue #372).
28
+
16
29
  Privacy: in-memory only, never persisted, never sent anywhere until the
17
- user opens the feedback modal, reviews the captured logs, and
18
- chooses to submit. Any single entry is truncated; the buffer is
19
- a fixed-size ring (page_feedback.log_limit).
30
+ reader opens the modal, reviews the captured lines, and submits.
31
+ Any single entry is truncated; the buffer is a fixed-size ring
32
+ (page_feedback.log_limit, default 40).
20
33
 
21
- Depends on: nothing — pure inline ES5, GitHub Pages-safe (no CDN).
34
+ Depends on: assets/js/fleet-feedback-capture.js (vendored, no CDN).
22
35
  ===================================================================
23
36
  {%- endcomment -%}
24
37
  {%- if site.page_feedback.enabled and site.page_feedback.capture_logs -%}
25
- <script>
26
- /* page-feedback: early console/error capture — see _includes/core/console-capture.html */
27
- (function () {
28
- "use strict";
29
- if (window.__zer0Feedback && window.__zer0Feedback.installed) { return; }
30
-
31
- var LIMIT = {{ site.page_feedback.log_limit | default: 40 | jsonify }};
32
- var MAX_ENTRY = 600; // truncate any single entry so the buffer stays small
33
- var start = (window.performance && performance.now) ? null : Date.now();
34
-
35
- var buffer = [];
36
- function now() { return start === null ? Math.round(performance.now()) : (Date.now() - start); }
37
-
38
- function stringify(value) {
39
- if (typeof value === "string") { return value; }
40
- if (value instanceof Error) {
41
- return (value.name || "Error") + ": " + (value.message || "") + (value.stack ? "\n" + value.stack : "");
42
- }
43
- try { return JSON.stringify(value); } catch (e) { return String(value); }
44
- }
45
-
46
- function push(level, args) {
47
- try {
48
- var parts = [];
49
- for (var i = 0; i < args.length; i++) { parts.push(stringify(args[i])); }
50
- var text = parts.join(" ");
51
- if (text.length > MAX_ENTRY) { text = text.slice(0, MAX_ENTRY) + "…"; }
52
- buffer.push({ t: now(), level: level, text: text });
53
- while (buffer.length > LIMIT) { buffer.shift(); }
54
- } catch (e) { /* logging must never break the page */ }
55
- }
56
-
57
- // Wrap console methods, preserving passthrough to the real console.
58
- if (window.console) {
59
- ["log", "info", "warn", "error", "debug"].forEach(function (level) {
60
- var original = console[level] ? console[level].bind(console) : null;
61
- console[level] = function () {
62
- push(level, arguments);
63
- if (original) { original.apply(null, arguments); }
64
- };
65
- });
66
- }
67
-
68
- // Uncaught errors and unhandled promise rejections.
69
- window.addEventListener("error", function (e) {
70
- if (!e) { return; }
71
- var where = e.filename ? " (" + e.filename + ":" + (e.lineno || 0) + ":" + (e.colno || 0) + ")" : "";
72
- push("error", [(e.message || "Script error") + where]);
73
- });
74
- window.addEventListener("unhandledrejection", function (e) {
75
- var reason = e && e.reason;
76
- var msg = reason && reason.message ? reason.message : stringify(reason);
77
- push("error", ["Unhandled promise rejection: " + msg]);
78
- });
79
-
80
- window.__zer0Feedback = {
81
- installed: true,
82
- logs: buffer,
83
- /** Snapshot the buffer (newest last) for the widget to read. */
84
- snapshot: function () { return buffer.slice(); },
85
- clear: function () { buffer.length = 0; }
86
- };
87
- })();
88
- </script>
38
+ <script src="{{ '/assets/js/fleet-feedback-capture.js' | relative_url }}"></script>
39
+ {%- comment -%}
40
+ The ring size is site configuration, so it is applied after the buffer
41
+ installs rather than baked into the vendored file (which must stay
42
+ byte-identical to the hub's).
43
+ {%- endcomment -%}
44
+ {%- if site.page_feedback.log_limit -%}
45
+ <script>if(window.__fleetFeedback){window.__fleetFeedback.limit={{ site.page_feedback.log_limit | jsonify }};}</script>
46
+ {%- endif -%}
89
47
  {%- endif -%}
@@ -16,12 +16,17 @@
16
16
  png_size : 32x32 # sizes attr for png (optional)
17
17
  apple_touch : /assets/images/apple-touch.png # iOS home-screen icon (optional)
18
18
  manifest : /site.webmanifest # PWA manifest (optional)
19
- theme_color : "#0d1117" # browser chrome color (optional)
19
+ theme_color : "#0d1117" # pin ONE chrome color (optional)
20
+ theme_color_light : "#ffffff" # light-scheme chrome (optional)
21
+ theme_color_dark : "#212529" # dark-scheme chrome (optional)
20
22
 
21
23
  With NO config at all this still emits the explicit
22
- /favicon.ico link (every consumer site carries one at root),
23
- and theme_color falls back to site.theme_color.main so the
24
- mobile address bar matches the site's design tokens.
24
+ /favicon.ico link (every consumer site carries one at root)
25
+ AND both theme-color tags. That last part is the point of the
26
+ fallbacks below: a remote_theme consumer does not inherit this
27
+ repo's _config.yml (see remote-theme-checklist.md), so a
28
+ config-gated tag emitted nothing at all on exactly the sites
29
+ this include exists to serve (issue #281).
25
30
  Notes: Page-invariant — safe to render via include_cached. All paths
26
31
  run through relative_url so baseurl deployments resolve.
27
32
  {%- endcomment -%}
@@ -40,7 +45,44 @@
40
45
  {%- if _fav.manifest %}
41
46
  <link rel="manifest" href="{{ _fav.manifest | relative_url }}">
42
47
  {%- endif %}
43
- {%- assign _fav_theme_color = _fav.theme_color | default: site.theme_color.main -%}
44
- {%- if _fav_theme_color %}
45
- <meta name="theme-color" content="{{ _fav_theme_color }}">
48
+ {%- comment -%}
49
+ theme-color drives mobile browser chrome (iOS Safari address/status bar,
50
+ the Chrome/Android task-switcher card). It must track the page SURFACE.
51
+
52
+ It used to fall back to site.theme_color.main, which is the brand ACCENT --
53
+ #007bff on this site -- so a dark-first theme advertised a bright blue
54
+ address bar. The defaults below are Bootstrap 5.3.3's own --bs-body-bg for
55
+ each scheme (:root #fff, [data-bs-theme=dark] #212529); the theme adds no
56
+ dark override of that variable, so they are the real computed surface.
57
+
58
+ WHICH SHAPE TO EMIT depends on how the mode is decided, because
59
+ `media="(prefers-color-scheme: ...)"` keys off the OS and nothing else:
60
+
61
+ - mode is pinned (color_mode_lock, or a non-auto color_mode_default)
62
+ -> ONE unconditional tag. A media pair would hand light chrome to an
63
+ OS-light visitor looking at a page this site renders dark.
64
+ - mode is `auto` -> the media pair, which is exactly what `auto` means.
65
+
66
+ A locked `auto` resolves to dark here, matching core/color-mode-init.html.
67
+
68
+ Known limitation, deliberately not solved here: an unlocked site lets a
69
+ visitor override the mode from the Appearance panel via localStorage, which
70
+ no static meta can follow. Keeping chrome in sync with the panel needs a
71
+ runtime hook in the toggle path -- tracked separately.
72
+ {%- endcomment -%}
73
+ {%- assign _tc_light = _fav.theme_color_light | default: '#ffffff' -%}
74
+ {%- assign _tc_dark = _fav.theme_color_dark | default: '#212529' -%}
75
+ {%- assign _tc_mode = site.color_mode_default | default: 'auto' -%}
76
+ {%- if _fav.theme_color %}
77
+ {%- comment -%} Back-compat: a consumer that pinned one colour keeps it. {%- endcomment %}
78
+ <meta name="theme-color" content="{{ _fav.theme_color }}">
79
+ {%- elsif site.color_mode_lock and _tc_mode == 'light' %}
80
+ <meta name="theme-color" content="{{ _tc_light }}">
81
+ {%- elsif site.color_mode_lock or _tc_mode == 'dark' %}
82
+ <meta name="theme-color" content="{{ _tc_dark }}">
83
+ {%- elsif _tc_mode == 'light' %}
84
+ <meta name="theme-color" content="{{ _tc_light }}">
85
+ {%- else %}
86
+ <meta name="theme-color" media="(prefers-color-scheme: light)" content="{{ _tc_light }}">
87
+ <meta name="theme-color" media="(prefers-color-scheme: dark)" content="{{ _tc_dark }}">
46
88
  {%- endif %}
@@ -20,12 +20,26 @@
20
20
  after </footer> is visually identical to the previous nesting.
21
21
  ===================================================================
22
22
  {%- endcomment -%}
23
- {%- assign _root_only_layouts = "landing,welcome,stats,sitemap-collection,setup,section,news,index,home,admin" | split: "," -%}
24
- {%- unless _root_only_layouts contains page.layout -%}
23
+ {%- comment -%}
24
+ The TOC FAB controls `#tocContents`, which navigation/sidebar-right.html
25
+ emits — and only _layouts/default.html includes that. This used to be a
26
+ DENYLIST of layouts to skip, which fails open: any layout not on the list got
27
+ the FAB whether or not it rendered the panel, and the list had already fallen
28
+ behind (404 and the book-* layouts were missing, so those pages shipped a FAB
29
+ pointing at nothing — issue #373).
30
+
31
+ Replaced with the positive gate from navigation/sidebar-config.html, which
32
+ fails safe: a new layout gets no FAB until it is declared as one that renders
33
+ the offcanvas. sidebar-config is included here rather than relied upon from
34
+ header.html because Liquid assigns propagate to the INCLUDING template, and
35
+ these are two sibling includes of root.html.
36
+ {%- endcomment -%}
37
+ {% include navigation/sidebar-config.html %}
38
+ {%- if sidebar_offcanvas_rendered -%}
25
39
  {% include navigation/toc-fab.html %}
26
40
  {%- comment -%} Local-graph FAB/panel are part of the Obsidian feature. {%- endcomment -%}
27
41
  {%- if site.obsidian.enabled != false -%}
28
42
  {% include navigation/local-graph-fab.html %}
29
43
  {% include navigation/local-graph.html %}
30
44
  {%- endif -%}
31
- {%- endunless -%}
45
+ {%- endif -%}