jekyll-theme-zer0 1.28.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1143 -13
- data/_data/README.md +2 -0
- data/_data/ai.yml +5 -3
- data/_data/ai_pricing.yml +36 -0
- data/_data/backlog.yml +507 -2
- data/_data/consumers.yml +157 -9
- data/_data/features.yml +303 -20
- data/_data/feedback_types.yml +17 -12
- data/_data/i18n/fr.yml +12 -7
- data/_data/i18n/manifest.yml +39 -12
- data/_data/ingredient_densities.yml +122 -0
- data/_data/landing.yml +5 -2
- data/_data/navigation/main.yml +16 -0
- data/_data/navigation/quickstart.yml +4 -0
- data/_data/recipe_courses.yml +64 -0
- data/_data/site_builder.yml +874 -0
- data/_data/theme-manifest.yml +160 -124
- data/_data/ui-text.yml +26 -0
- data/_includes/README.md +26 -2
- data/_includes/analytics/posthog.html +2 -2
- data/_includes/components/admin-links.html +2 -2
- data/_includes/components/admin-tabs.html +2 -2
- data/_includes/components/ai-chat.html +14 -11
- data/_includes/components/analytics-dashboard.html +8 -8
- data/_includes/components/author-bio.html +1 -1
- data/_includes/components/author-card.html +10 -2
- data/_includes/components/author-eeat.html +4 -4
- data/_includes/components/background-customizer.html +10 -10
- data/_includes/components/background-image.html +114 -0
- data/_includes/components/background-settings.html +28 -15
- data/_includes/components/collection-manager.html +5 -5
- data/_includes/components/component-showcase.html +13 -13
- data/_includes/components/config-editor.html +12 -12
- data/_includes/components/config-viewer.html +8 -8
- data/_includes/components/cookie-consent.html +15 -15
- data/_includes/components/cta-button.html +7 -2
- data/_includes/components/dev-shortcuts.html +7 -7
- data/_includes/components/env-dashboard.html +8 -8
- data/_includes/components/env-switcher.html +9 -9
- data/_includes/components/feature-card.html +2 -2
- data/_includes/components/halfmoon.html +2 -2
- data/_includes/components/info-section.html +42 -37
- data/_includes/components/js-cdn.html +15 -15
- data/_includes/components/language-toggle.html +168 -21
- data/_includes/components/mermaid.html +72 -435
- data/_includes/components/nanobar.html +5 -5
- data/_includes/components/nav-editor.html +2 -2
- data/_includes/components/nav-export.html +2 -2
- data/_includes/components/nav-overview.html +2 -2
- data/_includes/components/page-feedback.html +45 -30
- data/_includes/components/page-views-init.html +55 -0
- data/_includes/components/page-views.html +33 -0
- data/_includes/components/post-card.html +22 -22
- data/_includes/components/post-type-badge.html +2 -2
- data/_includes/components/powered-by.html +2 -2
- data/_includes/components/preview-image.html +6 -0
- data/_includes/components/quick-index.html +2 -2
- data/_includes/components/recipe-card.html +67 -0
- data/_includes/components/recipe-duration.html +50 -0
- data/_includes/components/recipe-grams.html +58 -0
- data/_includes/components/recipe-index.html +96 -0
- data/_includes/components/recipe-ingredients.html +90 -0
- data/_includes/components/recipe-meta.html +96 -0
- data/_includes/components/recipe-nutrition.html +57 -0
- data/_includes/components/recipe-qty.html +73 -0
- data/_includes/components/recipe-ratio.html +151 -0
- data/_includes/components/recipe-scaler.html +73 -0
- data/_includes/components/recipe-steps.html +86 -0
- data/_includes/components/recipe-temp.html +45 -0
- data/_includes/components/search-modal.html +29 -4
- data/_includes/components/searchbar.html +2 -2
- data/_includes/components/shortcuts-modal.html +3 -0
- data/_includes/components/svg-background.html +2 -2
- data/_includes/components/theme-customizer.html +2 -2
- data/_includes/components/theme-info.html +14 -7
- data/_includes/components/theme-preview-gallery.html +22 -22
- data/_includes/content/giscus.html +2 -2
- data/_includes/content/intro.html +8 -8
- data/_includes/content/jsonld-faq.html +2 -2
- data/_includes/content/jsonld-software.html +24 -5
- data/_includes/content/seo.html +4 -4
- data/_includes/content/sitemap.html +27 -27
- data/_includes/content/toc.html +183 -183
- data/_includes/core/branding.html +6 -6
- data/_includes/core/console-capture.html +32 -74
- data/_includes/core/favicon.html +49 -7
- data/_includes/core/footer-fabs.html +17 -3
- data/_includes/core/footer.html +49 -34
- data/_includes/core/head.html +110 -86
- data/_includes/core/header.html +76 -54
- data/_includes/docs/bootstrap-docs.html +8 -8
- data/_includes/landing/landing-install-cards.html +2 -2
- data/_includes/landing/landing-quick-links.html +1 -1
- data/_includes/navigation/admin-nav.html +2 -2
- data/_includes/navigation/nav-tree.html +8 -8
- data/_includes/navigation/navbar.html +12 -12
- data/_includes/navigation/section-sidebar.html +109 -27
- data/_includes/navigation/sidebar-config.html +36 -2
- data/_includes/navigation/sidebar-left.html +17 -16
- data/_includes/navigation/sidebar-right.html +8 -7
- data/_includes/obsidian/full-graph.html +2 -2
- data/_includes/setup/claude-session.html +72 -0
- data/_includes/setup/prereq-checklist.html +90 -0
- data/_includes/setup/wizard.html +924 -222
- data/_includes/stats/stats-categories.html +8 -8
- data/_includes/stats/stats-header.html +14 -14
- data/_includes/stats/stats-metrics.html +14 -14
- data/_includes/stats/stats-no-data.html +12 -12
- data/_includes/stats/stats-overview.html +6 -6
- data/_includes/stats/stats-tags.html +8 -8
- data/_layouts/404.html +38 -24
- data/_layouts/README.md +2 -0
- data/_layouts/admin.html +24 -24
- data/_layouts/article.html +43 -33
- data/_layouts/author.html +20 -20
- data/_layouts/authors.html +2 -2
- data/_layouts/book-abc.html +12 -12
- data/_layouts/book-story.html +15 -15
- data/_layouts/book.html +12 -12
- data/_layouts/collection.html +33 -33
- data/_layouts/cookbook.html +88 -0
- data/_layouts/default.html +31 -28
- data/_layouts/home.html +23 -23
- data/_layouts/index.html +10 -10
- data/_layouts/landing.html +17 -17
- data/_layouts/news.html +44 -44
- data/_layouts/note.html +38 -38
- data/_layouts/notebook.html +34 -34
- data/_layouts/recipe.html +274 -0
- data/_layouts/root.html +92 -55
- data/_layouts/section.html +62 -33
- data/_layouts/setup.html +3 -3
- data/_layouts/sitemap-collection.html +49 -49
- data/_layouts/stats.html +40 -40
- data/_layouts/tag.html +12 -12
- data/_layouts/welcome.html +21 -21
- data/_sass/components/_callout.scss +1 -1
- data/_sass/components/_footer.scss +37 -1
- data/_sass/components/_mermaid.scss +375 -0
- data/_sass/components/_page-views.scss +36 -0
- data/_sass/components/_recipe.scss +506 -0
- data/_sass/components/_setup-wizard.scss +764 -0
- data/_sass/components/_ui-enhancements.scss +6 -6
- data/_sass/core/_navbar.scss +261 -46
- data/_sass/layouts/_landing.scss +2 -2
- data/_sass/layouts/_navbar-extras.scss +14 -4
- data/_sass/tokens/_color.scss +6 -0
- data/_sass/tokens/_index.scss +2 -0
- data/_sass/tokens/_radius.scss +21 -0
- data/_sass/tokens/_typography.scss +4 -0
- data/_sass/utilities/_focus.scss +14 -0
- data/assets/css/main.scss +4 -0
- data/assets/js/ai-chat.js +47 -5
- data/assets/js/fleet-feedback-capture.js +124 -0
- data/assets/js/fleet-feedback.js +853 -0
- data/assets/js/mermaid-diagrams.js +1267 -0
- data/assets/js/modules/navigation/config.js +9 -6
- data/assets/js/modules/navigation/navbar.js +55 -0
- data/assets/js/modules/navigation/scroll-spy.js +315 -80
- data/assets/js/modules/theme/appearance.js +8 -2
- data/assets/js/obsidian-wiki-links.js +8 -3
- data/assets/js/page-feedback.js +125 -192
- data/assets/js/page-views.js +372 -0
- data/assets/js/recipe-scaler.js +501 -0
- data/assets/js/search-modal.js +36 -0
- data/assets/js/setup-wizard.js +2279 -226
- data/assets/js/site-builder.js +1834 -0
- data/assets/js/ui-enhancements.js +11 -3
- data/scripts/README.md +44 -0
- data/scripts/ai/README.md +38 -0
- data/scripts/ai/api_call.rb +124 -0
- data/scripts/ai/usage.rb +314 -0
- data/scripts/ai/usage_report.rb +225 -0
- data/scripts/bin/audit-consumer +39 -7
- data/scripts/bin/giscus-discussions +213 -14
- data/scripts/bin/manifest +35 -12
- data/scripts/ci/agent_review_result.py +164 -0
- data/scripts/ci/test_agent_review_result.py +172 -0
- data/scripts/ci/test_visual_evidence_autogen.py +341 -0
- data/scripts/ci/visual_evidence_autogen.py +1060 -0
- data/scripts/content-review.rb +20 -1
- data/scripts/design-system-check.rb +170 -0
- data/scripts/lib/audit.sh +42 -2
- data/scripts/lint-liquid-raw.rb +137 -0
- data/scripts/test/integration/mermaid +22 -8
- data/scripts/test/lib/run_tests.sh +3 -1
- data/scripts/test/lib/test_agent_review_result.sh +27 -0
- data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
- data/scripts/translate.rb +94 -16
- metadata +48 -2
|
@@ -61,24 +61,34 @@
|
|
|
61
61
|
{%- assign pf_theme = site.theme | default: site.remote_theme | default: "" -%}
|
|
62
62
|
|
|
63
63
|
{%- if pf_show_fab -%}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
{% comment %} Global feedback FAB (page-invariant; opens the modal) {% endcomment %}
|
|
65
|
+
{%- comment -%}
|
|
66
|
+
An anchor, not a button, and the href is load-bearing: the widget now
|
|
67
|
+
delegates issue assembly to assets/js/fleet-feedback.js, so if that script
|
|
68
|
+
fails to load (or JavaScript is off entirely) the FAB still reaches the
|
|
69
|
+
issue form instead of becoming a decorative circle. page-feedback.js
|
|
70
|
+
intercepts [data-pf-open] and opens the richer modal when it is running.
|
|
71
|
+
{%- endcomment -%}
|
|
72
|
+
<a id="pageFeedbackFab"
|
|
73
|
+
class="pf-fab btn shadow-lg position-fixed"
|
|
74
|
+
href="https://github.com/{{ pf_repo }}/issues/new?template=page_improvement.yml&labels=page-feedback"
|
|
75
|
+
role="button"
|
|
76
|
+
data-pf-open
|
|
77
|
+
target="_blank"
|
|
78
|
+
rel="noopener noreferrer"
|
|
79
|
+
aria-haspopup="dialog"
|
|
80
|
+
aria-controls="pageFeedbackModal"
|
|
81
|
+
title="{{ site.page_feedback.fab_label | default: 'Improve this page' | escape }}"
|
|
82
|
+
aria-label="{{ site.page_feedback.fab_label | default: 'Improve this page' | escape }}">
|
|
73
83
|
<i class="bi {{ site.page_feedback.fab_icon | default: 'bi-megaphone' }}" aria-hidden="true"></i>
|
|
74
|
-
</
|
|
84
|
+
</a>
|
|
75
85
|
{%- endif -%}
|
|
76
86
|
|
|
77
|
-
|
|
87
|
+
{% comment %} Feedback modal (self-contained overlay; controlled by page-feedback.js).
|
|
78
88
|
`position-fixed` is required, not cosmetic: it opts this <body> child out of
|
|
79
89
|
the .zer0-bg-body flattening rule (_sass/theme/_backgrounds.scss) that would
|
|
80
90
|
otherwise force position:relative; z-index:1 and let the cookie banner steal
|
|
81
|
-
the dialog's clicks.
|
|
91
|
+
the dialog's clicks. {% endcomment %}
|
|
82
92
|
<div class="pf-overlay position-fixed" id="pageFeedbackModal" role="dialog" aria-modal="true"
|
|
83
93
|
aria-labelledby="pfTitle" aria-describedby="pfIntro" hidden>
|
|
84
94
|
<div class="pf-dialog shadow-lg" role="document">
|
|
@@ -100,16 +110,18 @@
|
|
|
100
110
|
|
|
101
111
|
<form id="pfForm" class="pf-body" novalidate>
|
|
102
112
|
|
|
103
|
-
|
|
113
|
+
{% comment %} Step 1 — request type {% endcomment %}
|
|
104
114
|
<fieldset class="pf-field pf-types">
|
|
105
115
|
<legend class="pf-legend">What kind of feedback?</legend>
|
|
106
116
|
{%- comment -%}
|
|
107
117
|
_data/feedback_types.yml is optional for consumers (remote_theme
|
|
108
118
|
cannot ship _data). Without it the widget falls back to a minimal
|
|
109
119
|
generic taxonomy (see pf_fallback_types below) instead of rendering
|
|
110
|
-
an empty selector. The fallback
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
an empty selector. The fallback carries the four fleet-taxonomy
|
|
121
|
+
labels (bug/docs/feature/question) and no agent directive: a label
|
|
122
|
+
the consumer repo does not have is silently dropped by GitHub, so
|
|
123
|
+
naming them costs nothing and makes the issue pipeline-eligible the
|
|
124
|
+
moment the feedback fan-out creates them.
|
|
113
125
|
{%- endcomment -%}
|
|
114
126
|
{%- assign pf_group = "" -%}
|
|
115
127
|
{%- for t in site.data.feedback_types -%}
|
|
@@ -138,8 +150,7 @@
|
|
|
138
150
|
cannot ship _data). Without it, render this minimal generic
|
|
139
151
|
taxonomy instead of an empty selector. Ids/markup must stay in
|
|
140
152
|
sync with the fallback JSON in the #pageFeedbackTypes script
|
|
141
|
-
below
|
|
142
|
-
in the target repo or GitHub silently drops them) and no agent
|
|
153
|
+
below, which carries the fleet-taxonomy labels and no agent
|
|
143
154
|
directive.
|
|
144
155
|
{%- endcomment -%}
|
|
145
156
|
<p class="pf-types-group">This page</p>
|
|
@@ -183,7 +194,7 @@
|
|
|
183
194
|
{%- endfor -%}
|
|
184
195
|
</fieldset>
|
|
185
196
|
|
|
186
|
-
|
|
197
|
+
{% comment %} Step 2 — description {% endcomment %}
|
|
187
198
|
<div class="pf-field">
|
|
188
199
|
<label for="pfDescription" class="pf-label">Describe it</label>
|
|
189
200
|
<textarea id="pfDescription" class="form-control" rows="4"
|
|
@@ -194,14 +205,14 @@
|
|
|
194
205
|
</p>
|
|
195
206
|
</div>
|
|
196
207
|
|
|
197
|
-
|
|
208
|
+
{% comment %} Step 3 — what gets attached {% endcomment %}
|
|
198
209
|
<details class="pf-field pf-context" id="pfContextWrap">
|
|
199
210
|
<summary class="pf-summary">
|
|
200
211
|
<i class="bi bi-paperclip me-1" aria-hidden="true"></i>What gets attached
|
|
201
212
|
<span class="pf-context-count" id="pfContextCount"></span>
|
|
202
213
|
</summary>
|
|
203
214
|
<ul class="pf-context-list" id="pfContextList" aria-live="polite">
|
|
204
|
-
|
|
215
|
+
{% comment %} page title / url / path filled in by JS {% endcomment %}
|
|
205
216
|
</ul>
|
|
206
217
|
|
|
207
218
|
{%- if site.page_feedback.capture_logs -%}
|
|
@@ -221,7 +232,7 @@
|
|
|
221
232
|
</details>
|
|
222
233
|
|
|
223
234
|
{%- if pf_ai_available -%}
|
|
224
|
-
|
|
235
|
+
{% comment %} Step 4 — optional AI review (proxy + Claude Code OAuth) {% endcomment %}
|
|
225
236
|
<div class="pf-field pf-ai" id="pfAiWrap">
|
|
226
237
|
<div class="pf-ai-head">
|
|
227
238
|
<button type="button" class="btn btn-sm btn-outline-primary" id="pfAnalyze">
|
|
@@ -253,7 +264,7 @@
|
|
|
253
264
|
</div>
|
|
254
265
|
</div>
|
|
255
266
|
|
|
256
|
-
|
|
267
|
+
{% comment %} Widget configuration consumed by assets/js/page-feedback.js {% endcomment %}
|
|
257
268
|
<script id="pageFeedbackConfig" type="application/json">
|
|
258
269
|
{
|
|
259
270
|
"enabled": true,
|
|
@@ -275,19 +286,19 @@
|
|
|
275
286
|
}
|
|
276
287
|
</script>
|
|
277
288
|
|
|
278
|
-
|
|
289
|
+
{% comment %} Request-type taxonomy (from _data/feedback_types.yml; generic fallback
|
|
279
290
|
when the site ships no data file — keep in sync with the fallback markup
|
|
280
|
-
in the pf-types fieldset above)
|
|
291
|
+
in the pf-types fieldset above) {% endcomment %}
|
|
281
292
|
<script id="pageFeedbackTypes" type="application/json">
|
|
282
293
|
{% if site.data.feedback_types %}{{ site.data.feedback_types | jsonify }}{% else %}[
|
|
283
|
-
{"id":"fix-page","label":"Report a problem","icon":"bi-bug","group":"This page","scope":"page","description":"A typo, broken link, wrong information, or something rendering badly","labels":[],"agent":false,"placeholder":"What is wrong, where on the page, and what did you expect instead?"},
|
|
284
|
-
{"id":"improve-page","label":"Improve this page","icon":"bi-stars","group":"This page","scope":"page","description":"Polish the copy, structure, or presentation","labels":[],"agent":false,"placeholder":"What would make this page clearer, tighter, or more useful?"},
|
|
285
|
-
{"id":"feature","label":"Suggest a feature","icon":"bi-lightbulb","group":"The site","scope":"site","description":"An idea that would make the site more useful","labels":[],"agent":false,"placeholder":"Describe the feature and the problem it would solve."},
|
|
286
|
-
{"id":"question","label":"Ask a question","icon":"bi-question-circle","group":"The site","scope":"site","description":"Something unclear that is not exactly a bug","labels":[],"agent":false,"placeholder":"What would you like to know?"}
|
|
294
|
+
{"id":"fix-page","label":"Report a problem","icon":"bi-bug","group":"This page","scope":"page","description":"A typo, broken link, wrong information, or something rendering badly","labels":["bug"],"agent":false,"placeholder":"What is wrong, where on the page, and what did you expect instead?"},
|
|
295
|
+
{"id":"improve-page","label":"Improve this page","icon":"bi-stars","group":"This page","scope":"page","description":"Polish the copy, structure, or presentation","labels":["docs"],"agent":false,"placeholder":"What would make this page clearer, tighter, or more useful?"},
|
|
296
|
+
{"id":"feature","label":"Suggest a feature","icon":"bi-lightbulb","group":"The site","scope":"site","description":"An idea that would make the site more useful","labels":["feature"],"agent":false,"placeholder":"Describe the feature and the problem it would solve."},
|
|
297
|
+
{"id":"question","label":"Ask a question","icon":"bi-question-circle","group":"The site","scope":"site","description":"Something unclear that is not exactly a bug","labels":["question"],"agent":false,"placeholder":"What would you like to know?"}
|
|
287
298
|
]{% endif %}
|
|
288
299
|
</script>
|
|
289
300
|
|
|
290
|
-
|
|
301
|
+
{% comment %} Live page context (build-time front matter; runtime detail added by JS) {% endcomment %}
|
|
291
302
|
<script id="pageFeedbackContext" type="application/json">
|
|
292
303
|
{
|
|
293
304
|
"title": {{ page.title | default: site.title | jsonify }},
|
|
@@ -310,6 +321,10 @@
|
|
|
310
321
|
}
|
|
311
322
|
</script>
|
|
312
323
|
|
|
324
|
+
{% comment %} The shared fleet builder must be parsed before the widget: page-feedback.js
|
|
325
|
+
reads window.FleetFeedbackCore at load and bails without it. Both are `defer`, and
|
|
326
|
+
deferred scripts execute in document order, so this ordering is the dependency. {% endcomment %}
|
|
327
|
+
<script defer src="{{ '/assets/js/fleet-feedback.js' | relative_url }}"></script>
|
|
313
328
|
<script defer src="{{ '/assets/js/page-feedback.js' | relative_url }}"></script>
|
|
314
329
|
|
|
315
330
|
{%- endunless -%}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-083 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: page-views-init
|
|
4
|
+
Path: _includes/components/page-views-init.html
|
|
5
|
+
Purpose: Bootstrap the page-view counter — inject its configuration and
|
|
6
|
+
load the behaviour. Renders no visible markup; the badge lives
|
|
7
|
+
in components/page-views.html.
|
|
8
|
+
Params: none — configured via site.page_views
|
|
9
|
+
Depends on: assets/js/page-views.js
|
|
10
|
+
Included by: _includes/core/head.html (once per page)
|
|
11
|
+
Notes: Split from the badge include on purpose: the badge may appear
|
|
12
|
+
many times on a page, this must appear exactly once.
|
|
13
|
+
{%- endcomment -%}
|
|
14
|
+
|
|
15
|
+
{%- unless site.page_views.enabled -%}{%- comment -%} counter disabled {%- endcomment -%}
|
|
16
|
+
{%- else -%}
|
|
17
|
+
{%- comment -%}
|
|
18
|
+
`respect_dnt` / `respect_gpc` / `require_consent` default to the PostHog
|
|
19
|
+
privacy block so a site configures its privacy posture once. Liquid's
|
|
20
|
+
`default` filter treats `false` as "missing", so each flag is resolved with
|
|
21
|
+
an if-tag instead — otherwise an explicit `false` would silently flip true.
|
|
22
|
+
{%- endcomment -%}
|
|
23
|
+
{%- assign pv_dnt = true -%}
|
|
24
|
+
{%- if site.page_views.respect_dnt == false -%}{%- assign pv_dnt = false -%}{%- endif -%}
|
|
25
|
+
{%- assign pv_gpc = true -%}
|
|
26
|
+
{%- if site.page_views.respect_gpc == false -%}{%- assign pv_gpc = false -%}{%- endif -%}
|
|
27
|
+
{%- assign pv_consent = false -%}
|
|
28
|
+
{%- if site.page_views.require_consent -%}{%- assign pv_consent = true -%}{%- endif -%}
|
|
29
|
+
{%- assign pv_track = true -%}
|
|
30
|
+
{%- if site.page_views.track == false -%}{%- assign pv_track = false -%}{%- endif -%}
|
|
31
|
+
{%- assign pv_fallback = false -%}
|
|
32
|
+
{%- if site.page_views.fallback_local -%}{%- assign pv_fallback = true -%}{%- endif -%}
|
|
33
|
+
|
|
34
|
+
{% comment %} Page-view counter configuration consumed by assets/js/page-views.js {% endcomment %}
|
|
35
|
+
<script id="pageViewsConfig" type="application/json">
|
|
36
|
+
{
|
|
37
|
+
"enabled": true,
|
|
38
|
+
"provider": {{ site.page_views.provider | default: "local" | jsonify }},
|
|
39
|
+
"endpoint": {{ site.page_views.endpoint | default: "" | jsonify }},
|
|
40
|
+
"method": {{ site.page_views.method | default: "POST" | jsonify }},
|
|
41
|
+
"countKey": {{ site.page_views.count_key | default: "views" | jsonify }},
|
|
42
|
+
"dedupe": {{ site.page_views.dedupe | default: "session" | jsonify }},
|
|
43
|
+
"maxEntries": {{ site.page_views.max_entries | default: 500 }},
|
|
44
|
+
"track": {{ pv_track | jsonify }},
|
|
45
|
+
"respectDnt": {{ pv_dnt | jsonify }},
|
|
46
|
+
"respectGpc": {{ pv_gpc | jsonify }},
|
|
47
|
+
"requireConsent": {{ pv_consent | jsonify }},
|
|
48
|
+
"fallbackLocal": {{ pv_fallback | jsonify }},
|
|
49
|
+
"baseurl": {{ site.baseurl | default: "" | jsonify }},
|
|
50
|
+
"labelOne": {{ site.page_views.label_one | default: "view" | jsonify }},
|
|
51
|
+
"labelOther": {{ site.page_views.label_other | default: "views" | jsonify }}
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
<script defer src="{{ '/assets/js/page-views.js' | relative_url }}"></script>
|
|
55
|
+
{%- endunless -%}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-083 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: page-views
|
|
4
|
+
Path: _includes/components/page-views.html
|
|
5
|
+
Purpose: Inline "N views" badge for a page. Ships hidden and is revealed
|
|
6
|
+
by assets/js/page-views.js once a count is known, so a page
|
|
7
|
+
with no data never flashes "0 views".
|
|
8
|
+
Params: url (string, optional, default: page.url) — page to show
|
|
9
|
+
class (string, optional, default: "") — extra classes
|
|
10
|
+
icon (string, optional, default: "bi-eye")
|
|
11
|
+
separator (bool, optional, default: false) — render a
|
|
12
|
+
leading "•" INSIDE the badge, so the separator hides
|
|
13
|
+
with it in a meta row
|
|
14
|
+
Depends on: components/page-views-init.html (config + behaviour, loaded once
|
|
15
|
+
from core/head.html), _sass/components/_page-views.scss
|
|
16
|
+
Notes: Safe to include more than once per page — each badge resolves
|
|
17
|
+
its own `data-page-views` path. Paths are site-relative and
|
|
18
|
+
baseurl-free (page.url); page-views.js normalizes the runtime
|
|
19
|
+
location the same way.
|
|
20
|
+
{%- endcomment -%}
|
|
21
|
+
|
|
22
|
+
{%- unless site.page_views.enabled -%}{%- comment -%} counter disabled {%- endcomment -%}
|
|
23
|
+
{%- else -%}
|
|
24
|
+
{%- assign pv_path = include.url | default: page.url -%}
|
|
25
|
+
{%- assign pv_class = include.class | default: "" -%}
|
|
26
|
+
{%- assign pv_icon = include.icon | default: "bi-eye" -%}
|
|
27
|
+
<span class="page-views{% if pv_class != "" %} {{ pv_class }}{% endif %}" data-page-views="{{ pv_path | escape }}" hidden>
|
|
28
|
+
{%- if include.separator -%}<span class="page-views__sep mx-2" aria-hidden="true">•</span>{%- endif -%}
|
|
29
|
+
<i class="bi {{ pv_icon }} me-1" aria-hidden="true"></i>
|
|
30
|
+
<span class="page-views__count" data-page-views-count>0</span>
|
|
31
|
+
<span class="page-views__label" data-page-views-label>{{ site.page_views.label_other | default: "views" }}</span>
|
|
32
|
+
</span>
|
|
33
|
+
{%- endunless -%}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
{% comment %}
|
|
2
2
|
===================================================================
|
|
3
3
|
POST CARD COMPONENT - Reusable blog post card
|
|
4
4
|
===================================================================
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
- site.public_folder for image paths
|
|
42
42
|
- site.teaser for fallback image
|
|
43
43
|
===================================================================
|
|
44
|
-
|
|
44
|
+
{% endcomment %}
|
|
45
45
|
|
|
46
46
|
{% comment %} Parameter defaults {% endcomment %}
|
|
47
47
|
{% assign show_category = include.show_category | default: true %}
|
|
@@ -70,44 +70,44 @@
|
|
|
70
70
|
{% if render_col %}<div class="col">{% endif %}
|
|
71
71
|
<div class="card h-100 post-card border-0 shadow-sm {{ card_class }}">
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
{% comment %} ====================== {% endcomment %}
|
|
74
|
+
{% comment %} CARD IMAGE & BADGES {% endcomment %}
|
|
75
|
+
{% comment %} ====================== {% endcomment %}
|
|
76
76
|
<div class="position-relative">
|
|
77
|
-
|
|
77
|
+
{% comment %} Breaking News Badge {% endcomment %}
|
|
78
78
|
{% if include.post.breaking %}
|
|
79
79
|
<span class="badge bg-danger position-absolute top-0 start-0 m-2 z-1">
|
|
80
80
|
<i class="bi bi-lightning-fill me-1"></i>Breaking
|
|
81
81
|
</span>
|
|
82
82
|
{% endif %}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
{% comment %} Featured Badge {% endcomment %}
|
|
85
85
|
{% if include.post.featured %}
|
|
86
86
|
<span class="badge bg-warning text-dark position-absolute top-0 end-0 m-2 z-1">
|
|
87
87
|
<i class="bi bi-star-fill me-1"></i>Featured
|
|
88
88
|
</span>
|
|
89
89
|
{% endif %}
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
{% comment %} Post Type Badge {% endcomment %}
|
|
92
92
|
{% if show_post_type and include.post.post_type and include.post.post_type != "standard" and include.post.post_type != "featured" and include.post.post_type != "breaking" %}
|
|
93
93
|
<span class="position-absolute bottom-0 start-0 m-2 z-1">
|
|
94
94
|
{% include components/post-type-badge.html post_type=include.post.post_type %}
|
|
95
95
|
</span>
|
|
96
96
|
{% endif %}
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
{% comment %} Preview Image {% endcomment %}
|
|
99
99
|
<a href="{{ include.post.url | relative_url }}" class="text-decoration-none">
|
|
100
100
|
{% assign card_img = include.post.preview | default: site.teaser %}
|
|
101
101
|
{% include components/preview-image.html src=card_img alt=include.post.title class="card-img-top" %}
|
|
102
102
|
</a>
|
|
103
103
|
</div>
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
{% comment %} ====================== {% endcomment %}
|
|
106
|
+
{% comment %} CARD BODY {% endcomment %}
|
|
107
|
+
{% comment %} ====================== {% endcomment %}
|
|
108
108
|
<div class="card-body d-flex flex-column">
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
{% comment %} Category Badge {% endcomment %}
|
|
111
111
|
{% comment %} Category base is configurable (`category_base`, default `/news`).
|
|
112
112
|
Only link the badge when that category index page exists in the build;
|
|
113
113
|
otherwise render a plain badge so remote-theme consumers (whose category
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
</div>
|
|
136
136
|
{% endif %}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
{% comment %} Post Title {% endcomment %}
|
|
139
139
|
<h5 class="card-title mb-2">
|
|
140
140
|
<a href="{{ include.post.url | relative_url }}"
|
|
141
141
|
class="text-decoration-none text-body-emphasis stretched-link">
|
|
@@ -143,14 +143,14 @@
|
|
|
143
143
|
</a>
|
|
144
144
|
</h5>
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
{% comment %} Subtitle if available {% endcomment %}
|
|
147
147
|
{% if include.post.sub-title %}
|
|
148
148
|
<p class="card-subtitle text-muted small mb-2">
|
|
149
149
|
{{ include.post.sub-title }}
|
|
150
150
|
</p>
|
|
151
151
|
{% endif %}
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
{% comment %} Post Excerpt {% endcomment %}
|
|
154
154
|
{% if show_excerpt %}
|
|
155
155
|
<p class="card-text text-muted small flex-grow-1">
|
|
156
156
|
{{ include.post.excerpt | strip_html | truncate: 120 }}
|
|
@@ -159,13 +159,13 @@
|
|
|
159
159
|
|
|
160
160
|
</div>
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
{% comment %} ====================== {% endcomment %}
|
|
163
|
+
{% comment %} CARD FOOTER {% endcomment %}
|
|
164
|
+
{% comment %} ====================== {% endcomment %}
|
|
165
165
|
<div class="card-footer bg-transparent border-top-0">
|
|
166
166
|
<div class="d-flex justify-content-between align-items-center small text-muted">
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
{% comment %} Left: Author & Date {% endcomment %}
|
|
169
169
|
<div>
|
|
170
170
|
{% if show_author and include.post.author %}
|
|
171
171
|
<span class="me-2">
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
</span>
|
|
178
178
|
</div>
|
|
179
179
|
|
|
180
|
-
|
|
180
|
+
{% comment %} Right: Reading Time {% endcomment %}
|
|
181
181
|
{% if show_reading_time %}
|
|
182
182
|
<span>
|
|
183
183
|
<i class="bi bi-clock me-1"></i>{{ reading_time }}
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
|
|
187
187
|
</div>
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
{% comment %} Tags (compact) {% endcomment %}
|
|
190
190
|
{% if include.post.tags.size > 0 %}
|
|
191
191
|
<div class="mt-2">
|
|
192
192
|
{% for tag in include.post.tags limit: 3 %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% comment %} Feature: ZER0-064 {% endcomment %}
|
|
2
|
-
|
|
2
|
+
{% comment %}
|
|
3
3
|
===================================================================
|
|
4
4
|
POST TYPE BADGE COMPONENT - Visual indicator for article types
|
|
5
5
|
===================================================================
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- Bootstrap 5 badge component
|
|
30
30
|
- Bootstrap Icons
|
|
31
31
|
===================================================================
|
|
32
|
-
|
|
32
|
+
{% endcomment %}
|
|
33
33
|
|
|
34
34
|
{% assign type = include.post_type | default: "standard" %}
|
|
35
35
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
{% comment %}
|
|
2
2
|
file: powered-by.html
|
|
3
3
|
path:_includes/powered-by.html
|
|
4
4
|
description: This file is used to display the powered by section on the home page.
|
|
5
|
-
|
|
5
|
+
{% endcomment %}
|
|
6
6
|
|
|
7
7
|
<div class="row row-cols-1 row-cols-md-3 g-4">
|
|
8
8
|
{% for power in site.powered_by %}
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
style="height: 180px; object-fit: cover;"
|
|
11
11
|
-%}
|
|
12
12
|
|
|
13
|
+
WHICH INCLUDE: this one renders an <img> in the content flow. For cover art
|
|
14
|
+
painted as a CSS background on an otherwise empty box, use the sibling
|
|
15
|
+
components/background-image.html -- a background image is invisible to
|
|
16
|
+
assistive tech, so that case needs role="img" + aria-label (or aria-hidden
|
|
17
|
+
when purely decorative) rather than an alt attribute.
|
|
18
|
+
|
|
13
19
|
Convention: Preview paths can omit the /assets/ prefix.
|
|
14
20
|
The component will auto-prepend the assets_prefix from _config.yml.
|
|
15
21
|
Examples:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
{% comment %} Quick index of pages in the collection {% endcomment %}
|
|
2
2
|
{% if site.collections.pages %}
|
|
3
3
|
<ul>
|
|
4
4
|
<p>Quick Index</p>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</ul>
|
|
11
11
|
{% endif %}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
{% comment %} Post Categories {% endcomment %}
|
|
14
14
|
{% if page.sidebar == "searchCats" %}
|
|
15
15
|
<div id="categories">
|
|
16
16
|
</div>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-084 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: recipe-card
|
|
4
|
+
Path: _includes/components/recipe-card.html
|
|
5
|
+
Purpose: Index card for one recipe — photo, title, one-line description,
|
|
6
|
+
and the three facts a cook scans for: total time, what it makes,
|
|
7
|
+
and how hard it is.
|
|
8
|
+
Params: recipe (document, required) — a `recipes` collection doc
|
|
9
|
+
heading_level (number, optional, default: 3) — the title's
|
|
10
|
+
heading level, so a card never skips a level under whatever
|
|
11
|
+
heading precedes it
|
|
12
|
+
class (string, optional, default: "")
|
|
13
|
+
Depends on: components/preview-image.html, components/recipe-duration.html,
|
|
14
|
+
_sass/components/_recipe.scss (.recipe-card)
|
|
15
|
+
Notes: Total time comes from `times.total` or prep + cook + rest, so
|
|
16
|
+
the card never disagrees with the recipe page. The whole card is
|
|
17
|
+
one link for a large tap target; the facts row is plain text so
|
|
18
|
+
it stays readable when images fail to load.
|
|
19
|
+
{%- endcomment -%}
|
|
20
|
+
{%- if include.recipe == nil -%}
|
|
21
|
+
{%- comment -%} ERROR: recipe-card requires `recipe` {%- endcomment -%}
|
|
22
|
+
{%- else -%}
|
|
23
|
+
{%- assign _rc_r = include.recipe -%}
|
|
24
|
+
{%- assign _rc_img = _rc_r.image | default: _rc_r.preview | default: site.teaser -%}
|
|
25
|
+
{%- assign _rc_prep = _rc_r.times.prep | default: 0 -%}
|
|
26
|
+
{%- assign _rc_cook = _rc_r.times.cook | default: 0 -%}
|
|
27
|
+
{%- assign _rc_rest = _rc_r.times.rest | default: 0 -%}
|
|
28
|
+
{%- if _rc_r.times.total -%}
|
|
29
|
+
{%- assign _rc_total = _rc_r.times.total -%}
|
|
30
|
+
{%- else -%}
|
|
31
|
+
{%- assign _rc_total = _rc_prep | plus: _rc_cook | plus: _rc_rest -%}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- capture _rc_total_h -%}{%- include components/recipe-duration.html minutes=_rc_total -%}{%- endcapture -%}
|
|
34
|
+
{%- assign _rc_total_h = _rc_total_h | strip -%}
|
|
35
|
+
<article class="recipe-card h-100 {{ include.class | default: '' }}">
|
|
36
|
+
<a href="{{ _rc_r.url | relative_url }}" class="recipe-card-link d-flex flex-column h-100 text-decoration-none text-body">
|
|
37
|
+
{%- if _rc_img -%}
|
|
38
|
+
<div class="recipe-card-media">
|
|
39
|
+
{%- include components/preview-image.html src=_rc_img alt=_rc_r.title class="" -%}
|
|
40
|
+
</div>
|
|
41
|
+
{%- endif -%}
|
|
42
|
+
<div class="recipe-card-body">
|
|
43
|
+
{%- assign _rc_hl = include.heading_level | default: 3 -%}
|
|
44
|
+
<h{{ _rc_hl }} class="h5 recipe-card-title">{{ _rc_r.title }}</h{{ _rc_hl }}>
|
|
45
|
+
{%- if _rc_r.description -%}
|
|
46
|
+
<p class="recipe-card-description small text-body-secondary">{{ _rc_r.description | strip_html | truncate: 120 }}</p>
|
|
47
|
+
{%- endif -%}
|
|
48
|
+
<p class="recipe-card-facts small text-body-secondary mb-0">
|
|
49
|
+
{%- assign _rc_sep = false -%}
|
|
50
|
+
{%- if _rc_total_h != "" -%}
|
|
51
|
+
<span class="recipe-card-fact"><i class="bi bi-clock-history me-1" aria-hidden="true"></i>{{ _rc_total_h }}</span>
|
|
52
|
+
{%- assign _rc_sep = true -%}
|
|
53
|
+
{%- endif -%}
|
|
54
|
+
{%- if _rc_r.yield.amount -%}
|
|
55
|
+
{%- if _rc_sep %}<span class="mx-1" aria-hidden="true">•</span>{% endif -%}
|
|
56
|
+
<span class="recipe-card-fact"><i class="bi bi-pie-chart me-1" aria-hidden="true"></i>{{ _rc_r.yield.amount }} {{ _rc_r.yield.unit | default: "servings" | escape }}</span>
|
|
57
|
+
{%- assign _rc_sep = true -%}
|
|
58
|
+
{%- endif -%}
|
|
59
|
+
{%- if _rc_r.difficulty -%}
|
|
60
|
+
{%- if _rc_sep %}<span class="mx-1" aria-hidden="true">•</span>{% endif -%}
|
|
61
|
+
<span class="recipe-difficulty recipe-difficulty--{{ _rc_r.difficulty | downcase | strip }}">{{ _rc_r.difficulty | capitalize }}</span>
|
|
62
|
+
{%- endif -%}
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</a>
|
|
66
|
+
</article>
|
|
67
|
+
{%- endif -%}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-084 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: recipe-duration (value resolver — emits a bare string)
|
|
4
|
+
Path: _includes/components/recipe-duration.html
|
|
5
|
+
Purpose: Format a duration given in MINUTES, either for humans
|
|
6
|
+
("1 hr 30 min") or as an ISO 8601 duration for schema.org
|
|
7
|
+
("PT1H30M").
|
|
8
|
+
Params: minutes (number, required)
|
|
9
|
+
format (string, optional, default: "human") — "human" | "iso"
|
|
10
|
+
Depends on: nothing (pure Liquid arithmetic)
|
|
11
|
+
Notes: Emits nothing for a missing or zero duration, so callers can
|
|
12
|
+
test the captured value and skip the whole row. Days are not
|
|
13
|
+
special-cased — a 3-day cure reads as "72 hr", which is how
|
|
14
|
+
recipes actually write long ferments.
|
|
15
|
+
|
|
16
|
+
Liquid `assign` writes to the GLOBAL scope even inside an
|
|
17
|
+
include, so a helper called several times from one caller will
|
|
18
|
+
clobber the caller's variables if the names collide. Every
|
|
19
|
+
variable here is therefore prefixed `_rd_`, and the other recipe
|
|
20
|
+
components use their own prefixes. Keep that up when editing.
|
|
21
|
+
|
|
22
|
+
Capture it (this comment is brace-free so it cannot self-execute):
|
|
23
|
+
capture total -> include components/recipe-duration.html minutes=90
|
|
24
|
+
{%- endcomment -%}
|
|
25
|
+
{%- assign _rd_m = include.minutes -%}
|
|
26
|
+
{%- if _rd_m == nil or _rd_m == "" or _rd_m <= 0 -%}
|
|
27
|
+
{%- comment -%} recipe-duration: no duration — emitting nothing {%- endcomment -%}
|
|
28
|
+
{%- else -%}
|
|
29
|
+
{%- assign _rd_total = _rd_m | round -%}
|
|
30
|
+
{%- assign _rd_hours = _rd_total | divided_by: 60 -%}
|
|
31
|
+
{%- assign _rd_mins = _rd_total | modulo: 60 -%}
|
|
32
|
+
{%- if include.format == "iso" -%}
|
|
33
|
+
PT{% if _rd_hours > 0 %}{{ _rd_hours }}H{% endif %}{% if _rd_mins > 0 %}{{ _rd_mins }}M{% endif %}
|
|
34
|
+
{%- else -%}
|
|
35
|
+
{%- comment -%}
|
|
36
|
+
Built by appending rather than by emitting the separator from inside an
|
|
37
|
+
`if`: Liquid treats a block whose body is only whitespace as blank and
|
|
38
|
+
drops it, which silently swallowed the space in "12 hr 45 min".
|
|
39
|
+
{%- endcomment -%}
|
|
40
|
+
{%- assign _rd_out = "" -%}
|
|
41
|
+
{%- if _rd_hours > 0 -%}
|
|
42
|
+
{%- assign _rd_out = _rd_out | append: _rd_hours | append: " hr" -%}
|
|
43
|
+
{%- endif -%}
|
|
44
|
+
{%- if _rd_mins > 0 -%}
|
|
45
|
+
{%- if _rd_out != "" -%}{%- assign _rd_out = _rd_out | append: " " -%}{%- endif -%}
|
|
46
|
+
{%- assign _rd_out = _rd_out | append: _rd_mins | append: " min" -%}
|
|
47
|
+
{%- endif -%}
|
|
48
|
+
{{- _rd_out -}}
|
|
49
|
+
{%- endif -%}
|
|
50
|
+
{%- endif -%}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-084 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: recipe-grams (value resolver — emits a bare number)
|
|
4
|
+
Path: _includes/components/recipe-grams.html
|
|
5
|
+
Purpose: Convert one recipe quantity to grams so ratio tables and
|
|
6
|
+
baker's percentages can be computed at BUILD time (no JS needed).
|
|
7
|
+
Params: qty (number, required) — the amount as authored
|
|
8
|
+
unit (string, optional) — g, kg, oz, lb, ml, l, tsp,
|
|
9
|
+
tbsp, cup, fl oz, pint, …
|
|
10
|
+
grams_per_cup (number, optional) — density, required to convert
|
|
11
|
+
a VOLUME into a weight
|
|
12
|
+
Depends on: nothing (pure Liquid arithmetic)
|
|
13
|
+
Notes: Outputs a bare number rounded to 1 decimal, or nothing at all
|
|
14
|
+
when the unit is unknown/countable ("clove", "egg") or a volume
|
|
15
|
+
with no density. Callers MUST treat empty output as "unknown".
|
|
16
|
+
Mirrors the unit table in assets/js/recipe-scaler.js — change
|
|
17
|
+
both together.
|
|
18
|
+
|
|
19
|
+
Liquid `assign` writes to the GLOBAL scope even inside an
|
|
20
|
+
include, so every variable here is prefixed `_rg_` to keep
|
|
21
|
+
repeated calls from clobbering the caller's own variables.
|
|
22
|
+
|
|
23
|
+
Capture it (this comment is brace-free so it cannot self-execute):
|
|
24
|
+
capture grams -> include components/recipe-grams.html
|
|
25
|
+
qty=i.qty unit=i.unit grams_per_cup=density
|
|
26
|
+
{%- endcomment -%}
|
|
27
|
+
{%- if include.qty == nil or include.qty == "" -%}
|
|
28
|
+
{%- comment -%} ERROR: recipe-grams requires `qty` {%- endcomment -%}
|
|
29
|
+
{%- else -%}
|
|
30
|
+
{%- assign _rg_u = include.unit | default: "" | downcase | strip | replace: ".", "" | replace: "-", " " -%}
|
|
31
|
+
{%- assign _rg_mass = 0 -%}
|
|
32
|
+
{%- assign _rg_ml = 0 -%}
|
|
33
|
+
{%- case _rg_u -%}
|
|
34
|
+
{%- when "g" or "gram" or "grams" or "gr" -%}{%- assign _rg_mass = 1 -%}
|
|
35
|
+
{%- when "kg" or "kilogram" or "kilograms" -%}{%- assign _rg_mass = 1000 -%}
|
|
36
|
+
{%- when "mg" or "milligram" or "milligrams" -%}{%- assign _rg_mass = 0.001 -%}
|
|
37
|
+
{%- when "oz" or "ounce" or "ounces" -%}{%- assign _rg_mass = 28.3495 -%}
|
|
38
|
+
{%- when "lb" or "lbs" or "pound" or "pounds" -%}{%- assign _rg_mass = 453.592 -%}
|
|
39
|
+
{%- when "ml" or "milliliter" or "milliliters" or "millilitre" or "millilitres" or "cc" -%}{%- assign _rg_ml = 1 -%}
|
|
40
|
+
{%- when "l" or "liter" or "liters" or "litre" or "litres" -%}{%- assign _rg_ml = 1000 -%}
|
|
41
|
+
{%- when "dl" or "deciliter" or "deciliters" -%}{%- assign _rg_ml = 100 -%}
|
|
42
|
+
{%- when "tsp" or "teaspoon" or "teaspoons" -%}{%- assign _rg_ml = 4.92892 -%}
|
|
43
|
+
{%- when "tbsp" or "tbs" or "tablespoon" or "tablespoons" -%}{%- assign _rg_ml = 14.7868 -%}
|
|
44
|
+
{%- when "cup" or "cups" -%}{%- assign _rg_ml = 236.588 -%}
|
|
45
|
+
{%- when "fl oz" or "floz" or "fluid ounce" or "fluid ounces" -%}{%- assign _rg_ml = 29.5735 -%}
|
|
46
|
+
{%- when "pint" or "pints" or "pt" -%}{%- assign _rg_ml = 473.176 -%}
|
|
47
|
+
{%- when "quart" or "quarts" or "qt" -%}{%- assign _rg_ml = 946.353 -%}
|
|
48
|
+
{%- when "gallon" or "gallons" or "gal" -%}{%- assign _rg_ml = 3785.41 -%}
|
|
49
|
+
{%- endcase -%}
|
|
50
|
+
{%- if _rg_mass > 0 -%}
|
|
51
|
+
{%- assign _rg_g = include.qty | times: _rg_mass -%}
|
|
52
|
+
{{- _rg_g | round: 1 -}}
|
|
53
|
+
{%- elsif _rg_ml > 0 and include.grams_per_cup -%}
|
|
54
|
+
{%- assign _rg_vol = include.qty | times: _rg_ml -%}
|
|
55
|
+
{%- assign _rg_g = _rg_vol | times: include.grams_per_cup | divided_by: 236.588 -%}
|
|
56
|
+
{{- _rg_g | round: 1 -}}
|
|
57
|
+
{%- endif -%}
|
|
58
|
+
{%- endif -%}
|