{{/* Hugo Blox: Biography */}} {{/* Documentation: https://hugoblox.com/blocks/ */}} {{/* License: https://github.com/HugoBlox/kit/blob/main/LICENSE.md */}} {{/* Initialise */}} {{ $page := .wcPage }} {{ $block := .wcBlock }} {{ $content := $block.content }} {{ if not (reflect.IsMap $content) }}{{ $content = dict }}{{ end }} {{ $design := $block.design }} {{ if not (reflect.IsMap $design) }}{{ $design = dict }}{{ end }} {{ $username := "me" }} {{ $username_raw := index $content "username" }} {{ if eq (printf "%T" $username_raw) "string" }} {{ $username = strings.TrimSpace $username_raw }} {{ end }} {{ $profile := partial "functions/get_author_profile" $username }} {{ $avatar := $profile.avatar }} {{/* Avatar customization parameters */}} {{ $avatar_size := "medium" }} {{ $avatar_shape := "circle" }} {{ $avatar_design := index $design "avatar" }} {{ if reflect.IsMap $avatar_design }} {{ $size_raw := index $avatar_design "size" }} {{ if eq (printf "%T" $size_raw) "string" }} {{ $size_candidate := lower (strings.TrimSpace $size_raw) }} {{ if in (slice "small" "medium" "large" "xl" "xxl") $size_candidate }} {{ $avatar_size = $size_candidate }} {{ end }} {{ end }} {{ $shape_raw := index $avatar_design "shape" }} {{ if eq (printf "%T" $shape_raw) "string" }} {{ $shape_candidate := lower (strings.TrimSpace $shape_raw) }} {{ if in (slice "circle" "square" "rounded") $shape_candidate }} {{ $avatar_shape = $shape_candidate }} {{ end }} {{ end }} {{ end }} {{/* Size mappings optimized for 2025 standards: display_size -> [display_px, generation_px] */}} {{ $size_map := dict "small" (slice "150" "300") "medium" (slice "200" "400") "large" (slice "320" "640") "xl" (slice "400" "800") "xxl" (slice "500" "1000") }} {{ $size_config := index $size_map $avatar_size | default (index $size_map "medium") }} {{ $display_size := index $size_config 0 }} {{ $generation_size := index $size_config 1 }} {{/* Shape class mappings */}} {{ $shape_classes := dict "circle" "rounded-full" "square" "rounded-none" "rounded" "rounded-lg" }} {{ $shape_class := index $shape_classes $avatar_shape | default "rounded-full" }} {{ $img := "" }} {{ $banner := index $design "banner" }} {{ $banner_filename := "" }} {{ if reflect.IsMap $banner }} {{ with index $banner "filename" }}{{ $banner_filename = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ end }} {{ if $banner_filename }} {{/* Resolve image from page bundle, site assets, remote, or static URLs */}} {{ $image_resource := false }} {{ $image_url := "" }} {{ if $banner_filename }} {{ $image_path := strings.TrimSpace (printf "%v" $banner_filename) }} {{ $is_remote := or (strings.HasPrefix $image_path "http://") (strings.HasPrefix $image_path "https://") }} {{ if $is_remote }} {{ $remote := try (resources.GetRemote $image_path) }} {{ if and $remote (not $remote.Err) }} {{ $image_resource = $remote.Value }} {{ else }} {{/* If remote fetch fails, fall back to the original URL */}} {{ $image_url = $image_path }} {{ end }} {{ else }} {{/* Normalize common prefixes and dot paths */}} {{ $image_path = strings.TrimPrefix "/" $image_path }} {{ $image_path = strings.TrimPrefix "./" $image_path }} {{ $image_path = strings.TrimPrefix "assets/" $image_path }} {{ $image_path = strings.TrimPrefix "media/" $image_path }} {{ $normalized := path.Clean $image_path }} {{ if and $normalized (ne $normalized ".") }} {{/* Prefer page bundle image resources */}} {{ with $page }} {{ $image_resource = (.Resources.ByType "image").GetMatch $normalized }} {{ end }} {{ if not $image_resource }} {{/* Look in global assets/media - use resources.Get for exact path matching */}} {{ $image_resource = resources.Get (path.Join "media" $normalized) }} {{ end }} {{ if not $image_resource }} {{/* Static fallback (serves original size) */}} {{ $image_url = printf "/media/%s" $normalized }} {{ end }} {{ end }} {{ end }} {{ end }} {{ $img = $image_resource }} {{ if $img }} {{/* reflect.IsImageResourceProcessable → false for SVG; GIF skipped to preserve animation */}} {{ $canProcess := and (reflect.IsImageResourceProcessable $img) (ne $img.MediaType.SubType "gif") }} {{ if $canProcess }} {{ $responsive := partial "functions/process_responsive_image.html" (dict "image" $img "mode" "fill" "aspect_ratio" "16:9" "sizes" (slice 768 1024 1366 1920 2560) ) }}
{{ else }} {{/* SVG or GIF: pass through without responsive processing */}}
{{ end }} {{ else if $image_url }} {{/* Static fallback for remote/unprocessed images */}} {{ $is_external := or (strings.HasPrefix $image_url "http://") (strings.HasPrefix $image_url "https://") }}
{{ end }} {{ end }} {{ $profile_title := "" }} {{ with $profile.title }}{{ $profile_title = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ $profile_pronouns := "" }} {{ with $profile.pronouns }}{{ $profile_pronouns = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ $profile_role := "" }} {{ with $profile.role }}{{ $profile_role = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ $profile_bio := "" }} {{ with $profile.bio }}{{ $profile_bio = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ $status_icon := "" }} {{ $show_status := true }} {{ $show_status_raw := index $design "show_status" }} {{ if eq (printf "%T" $show_status_raw) "bool" }} {{ $show_status = $show_status_raw }} {{ end }} {{ if $show_status }} {{ with $profile.status }} {{ if reflect.IsMap . }} {{ $icon_raw := index . "icon" }} {{ if eq (printf "%T" $icon_raw) "string" }} {{ $status_icon = strings.TrimSpace $icon_raw }} {{ end }} {{ end }} {{ end }} {{ end }} {{ $affiliations := slice }} {{ $affiliations_raw := $profile.affiliations }} {{ if reflect.IsSlice $affiliations_raw }} {{ range $affiliations_raw }} {{ if reflect.IsMap . }} {{ $name := "" }} {{ $url := "" }} {{ with index . "name" }}{{ $name = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ with index . "url" }}{{ $url = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ if $name }} {{ $affiliations = $affiliations | append (dict "name" $name "url" $url) }} {{ end }} {{ end }} {{ end }} {{ end }} {{ $links := slice }} {{ $links_raw := $profile.links }} {{ $links_iter := slice }} {{ if reflect.IsSlice $links_raw }} {{ $links_iter = $links_raw }} {{ else if and $links_raw (reflect.IsMap $links_raw) }} {{ $links_iter = slice $links_raw }} {{ end }} {{ if gt (len $links_iter) 0 }} {{ range $links_iter }} {{ $url := "" }} {{ $icon := "" }} {{ $label := "" }} {{ if reflect.IsMap . }} {{ with index . "url" }}{{ $url = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ if not $url }} {{ with index . "link" }}{{ $url = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ end }} {{ with index . "icon" }}{{ $icon = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ with index . "label" }}{{ $label = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ else if eq (printf "%T" .) "string" }} {{ $url = strings.TrimSpace . }} {{ end }} {{ if $url }} {{ if not $icon }}{{ $icon = "hero/link" }}{{ end }} {{ $links = $links | append (dict "url" $url "icon" $icon "label" $label) }} {{ end }} {{ end }} {{ end }} {{ $bio_style := "" }} {{ $bio_design := index $design "biography" }} {{ if reflect.IsMap $bio_design }} {{ with index $bio_design "style" }}{{ $bio_style = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ end }} {{ $bio_override := "" }} {{ $bio_raw := index $content "text" }} {{ if $bio_raw }} {{ $bio_override = strings.TrimSpace (printf "%v" $bio_raw) }} {{ end }} {{ $bio_content := $profile_bio }} {{ if $bio_override }}{{ $bio_content = $bio_override }}{{ end }} {{ $button := index $content "button" }} {{ if not (reflect.IsMap $button) }}{{ $button = dict }}{{ end }} {{ $button_text := "" }} {{ $button_link := "" }} {{ with index $button "text" }}{{ $button_text = strings.TrimSpace (printf "%v" .) }}{{ end }} {{ with index $button "url" }}{{ $button_link = strings.TrimSpace (printf "%v" .) }}{{ end }}
{{ if $avatar }}
{{ $avatar_image := $avatar.Fill (printf "%sx%s Center" $generation_size $generation_size) }} {{ $profile_title }} {{ with $status_icon }}{{ . | emojify }}{{ end }}
{{ end }} {{/* Extract pronunciation for ruby annotation */}} {{ $name_pronunciation := "" }} {{ with $profile.name_pronunciation }} {{ if eq (printf "%T" .) "string" }} {{ $name_pronunciation = strings.TrimSpace . }} {{ end }} {{ end }} {{/* Name with optional ruby pronunciation */}} {{ if and $profile_title $name_pronunciation }}

{{ $profile_title }}{{ $name_pronunciation }}

{{ else }}
{{- $profile_title -}}
{{ end }} {{- with $profile_pronouns -}}
({{ . }})
{{- end -}} {{ with $profile_role }}

{{ . | markdownify | emojify }}

{{ end }} {{ range $affiliations }}
{{ $name := index . "name" }} {{ $url := index . "url" }} {{ if $url }} {{ $link := $url }} {{ $target := "" }} {{ $scheme := (urls.Parse $link).Scheme }} {{ if not $scheme }} {{ if not (hasPrefix $link "#") }} {{ $link = $link | relLangURL }} {{ end }} {{ else if in (slice "http" "https") $scheme }} {{ $target = "target=\"_blank\" rel=\"noopener\"" }} {{ end }}
{{ $name }}
{{ else }}
{{ $name }}
{{ end }}
{{ end }} {{ if gt (len $links) 0 }} {{ end }} {{ if $bio_content }}
{{ $bio_content | emojify | $page.RenderString }}
{{ end }} {{ if and $button_text $button_link }} {{ $button_href := $button_link }} {{ $button_target := "" }} {{ $button_scheme := (urls.Parse $button_href).Scheme }} {{ if not $button_scheme }} {{ if not (hasPrefix $button_href "#") }} {{ $button_href = $button_href | relLangURL }} {{ end }} {{ if eq (path.Ext $button_href) ".pdf" }}{{ $button_target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }} {{ else if in (slice "http" "https") $button_scheme }} {{ $button_target = "target=\"_blank\" rel=\"noopener\"" }} {{ end }} {{ $button_text }} {{ end }}