mirror of
https://github.com/tiennm99/iammiti99.git
synced 2026-10-14 04:16:16 +00:00
feat(theme): multi-section bio + per-link enhancements
Introduces multi-section bio cards and link groups for content organization. Link buttons now support dict-shape with image, featured, scheduled, rel, and note attributes. Schema Person flattens sections for SEO. RSS and single.html templates updated to use new link dict shape. Enables linktree-style content structuring.
This commit is contained in:
1 parent
740285fa17
commit
4d9107cbf7
6 files changed
+132
-22
No files matched your search
@@ -16,7 +16,16 @@
|
||||
<language>{{ site.Language.LanguageCode | default site.LanguageCode }}</language>
|
||||
<lastBuildDate>{{ $now.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>
|
||||
<atom:link href="{{ "index.xml" | absURL }}" rel="self" type="application/rss+xml" />
|
||||
{{- range site.Params.links }}
|
||||
{{- /* Flatten params.links + params.sections.*.links into a single list. */ -}}
|
||||
{{- $allLinks := slice -}}
|
||||
{{- if site.Params.sections -}}
|
||||
{{- range site.Params.sections -}}
|
||||
{{- range .links -}}{{- $allLinks = $allLinks | append . -}}{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $allLinks = site.Params.links -}}
|
||||
{{- end -}}
|
||||
{{- range $allLinks }}
|
||||
<item>
|
||||
<title>{{ .title | transform.XMLEscape }}</title>
|
||||
<link>{{ .url }}</link>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
{{- $tagline := site.Params.tagline -}}
|
||||
{{- $bio := site.Params.bio -}}
|
||||
{{- $links := site.Params.links -}}
|
||||
{{- $sections := site.Params.sections -}}
|
||||
{{- $layout := site.Params.layout | default "stack" -}}
|
||||
{{- $validLayouts := slice "stack" "grid" "inline" -}}
|
||||
{{- if not (in $validLayouts $layout) -}}
|
||||
{{- warnf "bonsai: unknown params.layout %q (expected stack|grid|inline), falling back to 'stack'" $layout -}}
|
||||
{{- $layout = "stack" -}}
|
||||
{{- $defaultLabel := i18n "nav_links_label" | default "Links" -}}
|
||||
{{- if and $sections $links -}}
|
||||
{{- warnf "bonsai: both params.sections and params.links set; sections win, flat links ignored" -}}
|
||||
{{- end -}}
|
||||
|
||||
<article class="bio">
|
||||
@@ -22,11 +22,37 @@
|
||||
<p class="bio__text">{{ . | markdownify }}</p>
|
||||
{{- end }}
|
||||
|
||||
{{- if $links }}
|
||||
<nav class="bio__links bio__links--{{ $layout }}" aria-label="{{ i18n "nav_links_label" | default "Links" }}">
|
||||
{{- range $links }}
|
||||
{{- partial "link-button.html" . -}}
|
||||
{{- end }}
|
||||
</nav>
|
||||
{{- if $sections -}}
|
||||
{{- range $i, $section := $sections -}}
|
||||
{{- $secLinks := $section.links -}}
|
||||
{{- if $secLinks -}}
|
||||
{{- $secLayout := $section.layout | default $layout -}}
|
||||
{{- $secTitle := $section.title -}}
|
||||
{{- $slug := "" -}}
|
||||
{{- with $secTitle }}{{ $slug = . | urlize }}{{ end -}}
|
||||
{{- if not $slug }}{{ $slug = printf "section-%d" (add $i 1) }}{{ end -}}
|
||||
<section class="bio__section"{{ with $secTitle }} aria-labelledby="section-{{ $slug }}"{{ else }} aria-label="{{ $defaultLabel }} {{ add $i 1 }}"{{ end }}>
|
||||
{{- with $secTitle }}
|
||||
<h2 id="section-{{ $slug }}" class="bio__section-title">{{ . }}</h2>
|
||||
{{- end }}
|
||||
{{- with $section.description }}
|
||||
<p class="bio__section-desc">{{ . | markdownify }}</p>
|
||||
{{- end }}
|
||||
{{ partial "link-group.html" (dict "links" $secLinks "layout" $secLayout "label" (or $secTitle $defaultLabel)) }}
|
||||
</section>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else if $links -}}
|
||||
{{ partial "link-group.html" (dict "links" $links "layout" $layout "label" $defaultLabel) }}
|
||||
{{- end -}}
|
||||
|
||||
{{- if site.Params.share }}
|
||||
{{ partial "share-button.html" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- if site.Params.vcard }}
|
||||
<a class="bio__vcard" href="{{ `vcard.vcf` | relURL }}" download>{{ i18n "save_contact" | default "Save contact" }}</a>
|
||||
{{- end }}
|
||||
|
||||
{{ partial "qr-block.html" . }}
|
||||
</article>
|
||||
@@ -1,12 +1,56 @@
|
||||
{{- $title := .title -}}
|
||||
{{- $url := .url -}}
|
||||
{{- $icon := .icon -}}
|
||||
{{- /* Render one link button.
|
||||
Context dict: { "link": {title,url,icon,image,featured,startDate,endDate,rel,note,...}, "analytics": params.analytics }
|
||||
Reads ONLY from its dict argument (per docs/code-standards.md partial composition rule). */ -}}
|
||||
{{- $l := .link -}}
|
||||
{{- $a := .analytics -}}
|
||||
{{- /* Per-link visibility window: skip rendering when now < startDate or now > endDate.
|
||||
Build-time evaluation only — re-evaluated at next site rebuild. */ -}}
|
||||
{{- $now := now -}}
|
||||
{{- $startOk := true -}}
|
||||
{{- $endOk := true -}}
|
||||
{{- with $l.startDate }}{{ $startOk = ge $now (time .) }}{{ end -}}
|
||||
{{- with $l.endDate }}{{ $endOk = le $now (time .) }}{{ end -}}
|
||||
{{- if and $startOk $endOk -}}
|
||||
{{- $title := $l.title -}}
|
||||
{{- $url := $l.url -}}
|
||||
{{- $icon := $l.icon -}}
|
||||
{{- $image := $l.image -}}
|
||||
{{- $note := $l.note -}}
|
||||
{{- $external := strings.HasPrefix $url "http" -}}
|
||||
<a class="link"
|
||||
{{- /* Class composition: .link + optional .link--featured */ -}}
|
||||
{{- $classes := "link" -}}
|
||||
{{- if $l.featured }}{{ $classes = printf "%s link--featured" $classes }}{{ end -}}
|
||||
{{- /* rel value for external links: always start with safe defaults, then append user rel */ -}}
|
||||
{{- $rel := "noopener noreferrer" -}}
|
||||
{{- with $l.rel }}{{ $rel = printf "%s %s" $rel . }}{{ end -}}
|
||||
{{- /* GA4 click-tracking attr: emit only when analytics enabled (caller passes the resolved dict). */ -}}
|
||||
{{- $trackClicks := and $a $a.measurementId (ne ($a.trackClicks | default true) false) -}}
|
||||
{{- /* UTM injection at build time for external links. Splits #fragment first so the
|
||||
query string lands BEFORE the fragment (preserving link semantics). */ -}}
|
||||
{{- if and $external $a $a.utmSource -}}
|
||||
{{- $fragment := "" -}}
|
||||
{{- if strings.Contains $url "#" -}}
|
||||
{{- $bits := split $url "#" -}}
|
||||
{{- $url = index $bits 0 -}}
|
||||
{{- $fragment = printf "#%s" (index $bits 1) -}}
|
||||
{{- end -}}
|
||||
{{- $sep := cond (strings.Contains $url "?") "&" "?" -}}
|
||||
{{- $utm := printf "utm_source=%s&utm_medium=%s" (urlquery $a.utmSource) (urlquery ($a.utmMedium | default "bio")) -}}
|
||||
{{- with $a.utmCampaign }}{{ $utm = printf "%s&utm_campaign=%s" $utm (urlquery .) }}{{ end -}}
|
||||
{{- $url = printf "%s%s%s%s" $url $sep $utm $fragment -}}
|
||||
{{- end -}}
|
||||
<a class="{{ $classes }}"
|
||||
href="{{ $url }}"
|
||||
{{- if $external }} target="_blank" rel="noopener noreferrer"{{ end }}>
|
||||
{{- with $icon }}
|
||||
<span class="link__icon" aria-hidden="true">{{ partial "icon.html" . }}</span>
|
||||
{{- if $external }} target="_blank" rel="{{ $rel }}"{{ end -}}
|
||||
{{- if $trackClicks }} data-analytics-event="link:{{ $l.title | urlize }}"{{ end }}>
|
||||
{{- if $image -}}
|
||||
<img class="link__thumb" src="{{ $image | strings.TrimPrefix "/" | relURL }}" alt="" width="24" height="24" loading="lazy" decoding="async" />
|
||||
{{- else if $icon -}}
|
||||
<span class="link__icon" aria-hidden="true">{{ partial "icon.html" $icon }}</span>
|
||||
{{- end }}
|
||||
<span class="link__title">{{ $title }}</span>
|
||||
<span class="link__title">
|
||||
{{- $title -}}
|
||||
{{- with $note }}<span class="link__note">{{ . }}</span>{{- end -}}
|
||||
</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,21 @@
|
||||
{{- /* Render a navigation block of links.
|
||||
Context dict: { "links": [...], "layout": "stack|grid|inline", "label": "..." }
|
||||
Used both by the flat-list rendering and per-section rendering. */ -}}
|
||||
{{- $links := .links -}}
|
||||
{{- $layout := .layout | default "stack" -}}
|
||||
{{- $label := .label | default (i18n "nav_links_label" | default "Links") -}}
|
||||
{{- $validLayouts := slice "stack" "grid" "inline" -}}
|
||||
{{- if not (in $validLayouts $layout) -}}
|
||||
{{- warnf "bonsai: unknown layout %q (expected stack|grid|inline), falling back to 'stack'" $layout -}}
|
||||
{{- $layout = "stack" -}}
|
||||
{{- end -}}
|
||||
{{- /* Resolve analytics once and pass into each link-button so the partial reads
|
||||
only its dict argument (per docs/code-standards.md partial composition rule). */ -}}
|
||||
{{- $analytics := site.Params.analytics -}}
|
||||
{{- if $links -}}
|
||||
<nav class="bio__links bio__links--{{ $layout }}" aria-label="{{ $label }}">
|
||||
{{- range $links }}
|
||||
{{- partial "link-button.html" (dict "link" . "analytics" $analytics) -}}
|
||||
{{- end }}
|
||||
</nav>
|
||||
{{- end -}}
|
||||
@@ -2,8 +2,17 @@
|
||||
Suppressed when site.Params.schema = false. */ -}}
|
||||
{{- if ne (site.Params.schema | default true) false -}}
|
||||
{{- $name := site.Params.name | default site.Title -}}
|
||||
{{- /* Flatten params.links + params.sections.*.links into a single list for sameAs. */ -}}
|
||||
{{- $allLinks := slice -}}
|
||||
{{- if site.Params.sections -}}
|
||||
{{- range site.Params.sections -}}
|
||||
{{- range .links -}}{{- $allLinks = $allLinks | append . -}}{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $allLinks = site.Params.links -}}
|
||||
{{- end -}}
|
||||
{{- $sameAs := slice -}}
|
||||
{{- range site.Params.links -}}
|
||||
{{- range $allLinks -}}
|
||||
{{- with .url -}}
|
||||
{{- if not (or (strings.HasPrefix . "mailto:") (strings.HasPrefix . "tel:")) -}}
|
||||
{{- $sameAs = $sameAs | append . -}}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{{ define "head_extra" }}
|
||||
<link rel="stylesheet" href="{{ `css/gallery.css` | relURL }}" />
|
||||
{{- $g := resources.Get "css/gallery.css" | resources.Minify | resources.Fingerprint "sha384" -}}
|
||||
<link rel="stylesheet" href="{{ $g.RelPermalink }}" integrity="{{ $g.Data.Integrity }}" crossorigin="anonymous" />
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
@@ -31,7 +32,7 @@
|
||||
<code class="variants-gallery__code">layout = "{{ .name }}"</code>
|
||||
<nav class="bio__links bio__links--{{ .name }}" aria-label="{{ .label }} sample">
|
||||
{{- range $sample }}
|
||||
{{- partial "link-button.html" . -}}
|
||||
{{- partial "link-button.html" (dict "link" . "analytics" site.Params.analytics) -}}
|
||||
{{- end }}
|
||||
</nav>
|
||||
</article>
|
||||
|
||||
Reference in new issue
Block a user