Skip to content

Commit 379bb08

Browse files
authored
Added new shortcodes + partials to support custom landing page (#273)
* Landing: Added new shortcodes + partials to support custom landing page * Landing: Added data-mf to card layout * Landing: Polished code + added error handling * Landing: Fixed issue with showAsCards applying universally * Landing: Fixed bug with old theme not rendering all custom content * Landing: Added extra doc to exampleSite
1 parent 707da5e commit 379bb08

File tree

10 files changed

+217
-90
lines changed

10 files changed

+217
-90
lines changed

assets/css/f5-hugo.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,16 @@ h3.card-title {
423423
font-weight: 400;
424424
}
425425

426+
/* Landing page cards */
427+
.text-content .card-layout {
428+
.card-section {
429+
margin-bottom: 1rem;
430+
431+
strong {
432+
font-weight: 500;
433+
}
434+
}
435+
}
426436
#f5-related,
427437
#nginx-products {
428438
width: 100%;

assets/css/v2/style.css

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,6 @@ nav {
677677

678678
h2 {
679679
font-size: 1.5rem;
680-
margin: 1rem 0 0rem 0;
681680
}
682681

683682
hr {
@@ -1193,6 +1192,35 @@ h6:has(a):hover {
11931192
color: oklch(var(--color-brand));
11941193
}
11951194

1195+
/* Landing page cards */
1196+
1197+
.text-content .card-layout {
1198+
grid-column: 1 / -1;
1199+
1200+
.card-section {
1201+
margin-bottom: 1rem;
1202+
1203+
strong {
1204+
font-weight: 500;
1205+
}
1206+
}
1207+
}
1208+
1209+
/* Optional grid layout */
1210+
.card-grid {
1211+
display: grid;
1212+
grid-template-columns: repeat(auto-fit, minmax(120px, 500px));
1213+
gap: 1.5rem;
1214+
margin-top: 1rem;
1215+
1216+
.card-container {
1217+
border: 1px solid oklch(var(--color-codeblock-border));
1218+
box-shadow: 3px 3px 0px oklch(var(--color-shadow));
1219+
padding: 1rem 2rem 2rem 2rem;
1220+
margin-bottom: 1.5rem;
1221+
}
1222+
}
1223+
11961224
/* MARK: Tables
11971225
*/
11981226
table {

exampleSite/content/test-product/_index.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,26 @@
22
description: Test pages for nginx-hugo-theme
33
title: Test pages
44
weight: 100
5+
hasCustomContent: true
56
---
7+
<!-- <card-layout> - Available params: title (required: string)-->
8+
{{< card-layout >}}
9+
<!-- <card-section> - Available params: title (required: string), showAsCards (optional: boolean, default false) -->
10+
<!-- If there is no "title" for <card-section>, it is implied it is the main content section and not a new content section -->
11+
{{< card-section >}}
12+
{{< card title="Call Out usages" >}}
13+
<!-- <card> - Available params: title (required: string), titleUrl (optional: string, relative path or absolute URL (e.g. https://google.com)) -->
14+
Examples for call-out shortcode
15+
{{</ card >}}
16+
{{< card title="Code Block usages" >}}
17+
Examples for codeblock shortcode
18+
{{</ card >}}
19+
{{</ card-section >}}
20+
21+
# Other Products on ExampleSite
22+
{{< card-section title="NGINX" showAsCards="true" >}}
23+
{{< card title="NGINX Plus" titleUrl="/nginx/" >}}
24+
Installing NGINX
25+
{{</ card >}}
26+
{{</ card-section >}}
27+
{{</ card-layout >}}

layouts/_default/list.html

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,22 @@
2929
{{ end }}
3030
</section>
3131
<h1>{{ .Title }}</h1>
32-
{{ .Content }}
3332

3433
{{ partial "banner" . }}
3534

36-
{{ if (lt .WordCount 1) }}
37-
{{ range .Pages.ByWeight }}
38-
<h2>
39-
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ .Title }}</a>
40-
</h2>
35+
{{ $hasCustomContent := .Params.hasCustomContent | default false }}
36+
{{ if $hasCustomContent }}
37+
{{ .Page.Scratch.Set "custom-landing-page-file-name" "custom-landing-page.html" }}
38+
{{ .Page.Scratch.Set "custom-landing-page-context" . }}
39+
{{ .Content }}
40+
{{ else }}
41+
{{ .Content }}
42+
{{ range .Pages.ByWeight }}
43+
<h2>
44+
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ .Title }}</a>
45+
</h2>
46+
{{ end }}
4147
{{ end }}
42-
{{end}}
4348

4449
<hr>
4550
{{ if .Page.Lastmod }}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{{ $cards := .Page.Scratch.Get "cards" }}
2+
{{ $showAsCards := index ( .Page.Scratch.Get "showAsCards") "main" }}
3+
{{ $class := "card-grid wide"}}
4+
5+
<div class="{{ if eq $showAsCards "true" }}{{ $class }}{{ end }}">
6+
<!-- Old frame -->
7+
<section data-mf="false">
8+
<div class="row">
9+
<div class="card-deck">
10+
{{ range .Pages.GroupBy "Section" }}
11+
{{ range .Pages.ByWeight }}
12+
{{ $title := .Title }}
13+
<div class="col-md-5 card">
14+
<div class="card-body">
15+
<h3 class="card-title" style="display: flex; align-items: center; gap: 5px;">
16+
<i class="fas fa-{{if eq .Kind "page"}}file-alt{{else}}book{{end}} fa-lg card-img-top"></i>
17+
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ .Title }}</a>
18+
</h3>
19+
{{ range $cards }}
20+
{{ if eq .title $title }}
21+
<p>{{ .content }}</p>
22+
{{ end }}
23+
{{ end }}
24+
</div>
25+
</div>
26+
{{ end }}
27+
{{ end }}
28+
</div>
29+
</div>
30+
</section>
31+
32+
<!-- Mainframe -->
33+
<div data-mf="true" style="display: none;">
34+
{{ range .Pages.ByWeight }}
35+
{{ $title := .Title }}
36+
<div class="card-container">
37+
<h2>
38+
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ $title }}</a>
39+
</h2>
40+
{{ range $cards }}
41+
{{ if eq .title $title }}
42+
<p>{{- .content -}}</p>
43+
{{ end }}
44+
{{ end }}
45+
</div>
46+
{{ end }}
47+
</div>
48+
</div>

layouts/partials/list-main.html

Lines changed: 24 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -10,91 +10,33 @@ <h1 class="bd-title">
1010
{{ .Description | markdownify }}
1111
</p>
1212
{{ end}}
13-
{{ if .Content }}
14-
<p>
15-
{{ .Content | markdownify }}
16-
</p>
17-
{{ end }}
18-
1913
{{ partial "banner" .}}
20-
</div>
21-
</div>
22-
23-
{{ if or (lt .WordCount 1) (eq $PageTitle "F5 NGINX One Console") (eq $PageTitle "F5 NGINX App Protect DoS") (eq $PageTitle "F5 NGINX Plus") }}
24-
<section>
25-
<div class="row">
26-
<div class="card-deck">
27-
{{ range .Pages.GroupBy "Section" }}
28-
{{ range .Pages.ByWeight }}
29-
<div class="col-md-5 card">
30-
<div class="card-body">
14+
{{ $hasCustomContent := .Params.hasCustomContent | default false }}
15+
{{ if $hasCustomContent }}
16+
{{ .Page.Scratch.Set "custom-landing-page-file-name" "custom-landing-page.html" }}
17+
{{ .Page.Scratch.Set "custom-landing-page-context" . }}
18+
{{ .Content }}
19+
{{ else }}
20+
<section data-mf="false">
21+
<div class="row">
22+
<div class="card-deck">
23+
{{ range .Pages.GroupBy "Section" }}
24+
{{ range .Pages.ByWeight }}
25+
{{ $title := .Title }}
26+
<div class="col-md-5 card">
27+
<div class="card-body">
3128
<h3 class="card-title" style="display: flex; align-items: center; gap: 5px;">
32-
<i class="fas fa-{{if eq .Kind "page"}}file-alt{{else}}book{{end}} fa-lg card-img-top"></i>
33-
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ .Title }}</a>
29+
<i class="fas fa-{{if eq .Kind "page"}}file-alt{{else}}book{{end}} fa-lg card-img-top"></i>
30+
<a href="{{ if .Params.url}}{{ .Params.url}}{{else}}{{ .Permalink }}{{end}}">{{ .Title }}</a>
3431
</h3>
35-
{{ if and (eq $PageTitle "F5 NGINX One Console") (eq .Title "How-to guides") }}
36-
<ul style="padding-top: 10px;">
37-
{{ range .Pages }}
38-
{{ if eq .Kind "section" }}
39-
{{ range .Pages }}
40-
<li><a href="{{ .Permalink }}"> {{ .Title }}</a></li>
41-
{{ end }}
42-
{{ end }}
43-
{{ end }}
44-
</ul>
45-
{{ end }}
46-
{{ if and (eq $PageTitle "F5 NGINX One Console") (eq .Title "API")}}
47-
<ul style="padding-top: 10px;">
48-
{{ range .Pages }}
49-
<li><a href="{{ .Permalink }}"> {{ .Title }}</a></li>
50-
{{ end }}
51-
</ul>
52-
{{ end }}
53-
{{ if and (eq $PageTitle "F5 NGINX One Console") (eq .Title "Changelog") }}
54-
{{ partial "changelog-date.html" . }}
55-
{{ end }}
32+
</div>
5633
</div>
57-
</div>
34+
{{ end }}
5835
{{ end }}
59-
{{ end }}
60-
</div>
61-
{{ if eq $PageTitle "F5 NGINX One Console" }}
62-
<h1 class="bd-title" style="margin-top: 15px;">Other Products</h1>
63-
{{ $nginxProducts := slice
64-
(dict "title" "NGINX Instance Manager" "url" "/nginx-instance-manager" "imgSrc" "NGINX-Instance-Manager-product-icon" "type" "local-console-option" "description" "Track and control NGINX Open Source and NGINX Plus instances.")
65-
(dict "title" "NGINX Ingress Controller" "url" "/nginx-ingress-controller" "imgSrc" "NGINX-Ingress-Controller-product-icon" "type" "kubernetes-solutions" "description" "Kubernetes traffic management with API gateway, identity, and observability features.")
66-
(dict "title" "NGINX Gateway Fabric" "url" "/nginx-gateway-fabric" "imgSrc" "NGINX-product-icon" "type" "kubernetes-solutions" "description" "Next generation Kubernetes connectivity using the Gateway API.")
67-
(dict "title" "NGINX App Protect WAF" "url" "/nginx-app-protect-waf" "imgSrc" "NGINX-App-Protect-WAF-product-icon" "type" "security" "description" "Lightweight, high-performance, advanced protection against Layer 7 attacks on your apps and APIs.")
68-
(dict "title" "NGINX App Protect DoS" "url" "/nginx-app-protect-dos" "imgSrc" "NGINX-App-Protect-DoS-product-icon" "type" "security" "description" "Defend, adapt, and mitigate against Layer 7 denial-of-service attacks on your apps and APIs.")
69-
(dict "title" "NGINX Plus" "url" "/nginx" "imgSrc" "NGINX-Plus-product-icon-RGB" "type" "modern-app-delivery" "description" "The all-in-one load balancer, reverse proxy, web server, content cache, and API gateway.")
70-
(dict "title" "NGINX Open Source" "url" "https://nginx.org/en/docs/" "imgSrc" "NGINX-product-icon" "type" "modern-app-delivery" "description" "The open source all-in-one load balancer, content cache, and web server")
71-
}}
72-
{{ $groupedProducts := dict
73-
"local-console-option" (where $nginxProducts "type" "local-console-option")
74-
"kubernetes-solutions" (where $nginxProducts "type" "kubernetes-solutions")
75-
"security" (where $nginxProducts "type" "security")
76-
"modern-app-delivery" (where $nginxProducts "type" "modern-app-delivery")
77-
}}
78-
{{ range $type, $products := $groupedProducts }}
79-
<div class="card-deck">
80-
<p style="margin-left: 15px; width: 100%; font-weight: bold;">{{ $type | humanize | title }}</p>
81-
{{ range $products }}
82-
<div class="card" style="margin-top: 0px; {{ if eq (len $products) 1 }}max-width: calc(50% - 30px);{{ else }}min-width: 40%;{{ end }}">
83-
<div class="card-body">
84-
<h3 class="card-title" style="display: flex; align-items: center;">
85-
<img class="card-img-top" src="{{ .Site.BaseURL }}/images/icons/{{ .imgSrc }}.png"/>
86-
<a href="{{ if eq .title "NGINX Open Source" }}{{ .url }}{{ else }}{{ .Site.BaseURL }}{{ .url }}{{ end }}">{{ .title }}</a>
87-
</h3>
88-
<p >
89-
{{ if .description }}{{ .description | markdownify }}{{ end }}
90-
</p>
91-
</div>
92-
</div>
93-
{{ end }}
94-
</div>
95-
{{ end }}
96-
{{ end }}
97-
</div>
98-
</section>
99-
{{end}}
36+
</div>
37+
</div>
38+
</section>
39+
{{ end }}
40+
</div>
41+
</div>
10042
</div>

layouts/shortcodes/card-layout.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<!-- Render the main content first with modifications, then render the custom content -->
2+
{{ $customLandingPageFileName := .Page.Scratch.Get "custom-landing-page-file-name" }}
3+
{{ $customLandingPageContext := .Page.Scratch.Get "custom-landing-page-context" }}
4+
{{ partial $customLandingPageFileName $customLandingPageContext }}
5+
<div class="card-layout">{{- .Inner | markdownify -}}</div>

layouts/shortcodes/card-section.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{{ $title := .Get "title" }}
2+
{{ $showAsCardsParam := .Get "showAsCards" | default "false"}}
3+
{{- /* Validate the parameter strictly */ -}}
4+
{{- if not (in (slice "true" "false") $showAsCardsParam) -}}
5+
{{- warnf "The '<card-section>' Shortcode parameter 'showAsCards' must be 'true' or 'false', but got: '%s'. This will now default to 'false'" $showAsCardsParam -}}
6+
{{- end -}}
7+
{{- $showAsCards := cond (eq $showAsCardsParam "true") "true" "false" -}}
8+
{{- $current := .Page.Scratch.Get "showAsCards" | default (dict) -}}
9+
{{- $newShowAsCards := dict ($title | default "main") ($showAsCards) -}}
10+
{{- .Page.Scratch.Set "showAsCards" (merge $current ($newShowAsCards)) -}}
11+
{{- $class := "card-grid wide" -}}
12+
{{- /* Validate that the parent is card-layout */ -}}
13+
{{ if eq .Parent.Name "card-layout"}}
14+
<div class="card-section" data-mf="true" style="display: none;">
15+
{{- if $title -}}
16+
<strong class="card-section-title">{{- $title -}}</strong>
17+
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }} {{ end }}">{{- .Inner -}}</div>
18+
{{ end }}
19+
</div>
20+
<div class="row" data-mf="false">
21+
{{- if $title -}}
22+
<strong class="card-section-title">{{- $title -}}</strong>
23+
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }} {{ end }} card-deck">{{- .Inner -}}</div>
24+
{{ end }}
25+
</div>
26+
{{ else }}
27+
{{ errorf "The '<card-section>' must be nested directly inside the shortcode '<card-layout>'. Please see the exampleSite for an example of usage." }}
28+
{{ end }}

layouts/shortcodes/card.html

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{{- $title := .Get "title" -}}
2+
{{- $titleUrl := .Get "titleUrl" | default "/" -}}
3+
{{- $icon := .Get "icon" | default "NGINX-product-icon" -}}
4+
{{- $current := .Page.Scratch.Get "cards" | default (slice) -}}
5+
{{- $newCard := dict "title" ($title) "content" (.Inner) -}}
6+
{{- .Page.Scratch.Set "cards" ($current | append $newCard) -}}
7+
{{- /* Validate that the parent is card-section */ -}}
8+
{{- if eq .Parent.Name "card-section" -}}
9+
<div class="card-container" style="display: none;" data-mf="true">
10+
{{- if $title -}}
11+
{{- if $titleUrl -}}
12+
<h2 class="card-title"><a href="{{- $titleUrl -}}">{{- $title -}}</a></h2>
13+
{{- else -}}
14+
<h2 class="card-title">{{- $title -}}</h2>
15+
{{- end -}}
16+
{{- else -}}
17+
{{ errorf "Mainframe: Missing param 'title'" }}
18+
{{- end -}}
19+
<p>{{- .Inner -}}</p>
20+
</div>
21+
<div class="col-md-5 card" data-mf="false">
22+
<div class="card-body">
23+
<h3 class="card-title" style="display: flex; align-items: center; gap: 5px;">
24+
{{- if $icon -}}
25+
<img class="card-img-top" src="{{ .Site.BaseURL }}/images/icons/{{ $icon }}.png"/>
26+
{{- end -}}
27+
{{- if ($title) -}}
28+
<a href="{{- $titleUrl -}}">{{- $title -}}</a>
29+
{{- else -}}
30+
{{ errorf "Old theme: Missing param 'title'" }}
31+
{{- end -}}
32+
</h3>
33+
<p>{{- .Inner -}}</p>
34+
</div>
35+
</div>
36+
{{- else -}}
37+
{{ errorf "The '<card>' must be nested directly inside the shortcode '<card-section>'. Please see the exampleSite for an example of usage." }}
38+
{{- end -}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{ partial "changelog-date.html" . }}

0 commit comments

Comments
 (0)