{{/* Hugo Blox: Biography 3 */}} {{/* 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 }} {{ $author := "me" }} {{ $authorRaw := index $content "username" }} {{ if eq (printf "%T" $authorRaw) "string" }} {{ $author = $authorRaw }} {{ end }} {{ $profile := partial "functions/get_author_profile" $author }} {{ $avatar := $profile.avatar }} {{ $headings := index $content "headings" }} {{ if not (reflect.IsMap $headings) }}{{ $headings = dict }}{{ end }} {{/* Avatar customization parameters */}} {{ $avatar_size := "large" }} {{ $avatar_shape := "circle" }} {{ $avatar_config := index $design "avatar" }} {{ if and $avatar_config (reflect.IsMap $avatar_config) }} {{ $avatar_size_raw := index $avatar_config "size" }} {{ if eq (printf "%T" $avatar_size_raw) "string" }} {{ $avatar_size = $avatar_size_raw }} {{ end }} {{ $avatar_shape_raw := index $avatar_config "shape" }} {{ if eq (printf "%T" $avatar_shape_raw) "string" }} {{ $avatar_shape = $avatar_shape_raw }} {{ end }} {{ end }} {{/* Profile name typography */}} {{ $name_size := "lg" }} {{ $name_config := index $design "name" }} {{ if and $name_config (reflect.IsMap $name_config) }} {{ $name_size_raw := index $name_config "size" }} {{ if eq (printf "%T" $name_size_raw) "string" }} {{ $name_size = $name_size_raw }} {{ end }} {{ end }} {{ $name_class_map := dict "xs" "text-xl sm:text-2xl lg:text-3xl" "sm" "text-2xl sm:text-3xl lg:text-4xl" "md" "text-3xl sm:text-4xl lg:text-5xl" "lg" "text-4xl sm:text-5xl lg:text-6xl" "xl" "text-5xl sm:text-6xl lg:text-7xl" }} {{ $name_class := index $name_class_map $name_size | default (index $name_class_map "lg") }} {{/* 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 "large") }} {{ $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" }} {{ $banner_filename := "" }} {{ $banner_config := index $design "banner" }} {{ if and $banner_config (reflect.IsMap $banner_config) }} {{ $banner_raw := index $banner_config "filename" }} {{ if eq (printf "%T" $banner_raw) "string" }} {{ $banner_filename = $banner_raw }} {{ end }} {{ end }} {{ $bio_style := "" }} {{ $bio_config := index $design "biography" }} {{ if and $bio_config (reflect.IsMap $bio_config) }} {{ $bio_style_raw := index $bio_config "style" }} {{ if eq (printf "%T" $bio_style_raw) "string" }} {{ $bio_style = $bio_style_raw }} {{ end }} {{ end }}
{{/* Add subtle top gradient for navbar transition */}}
{{/* Left Column: Flexible span */}}
{{/* Banner Image */}} {{ $img := "" }} {{/* 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 }} {{ $image_url = $image_path }} {{ end }} {{ else }} {{ $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 ".") }} {{ with $page }} {{ $image_resource = (.Resources.ByType "image").GetMatch $normalized }} {{ end }} {{ if not $image_resource }} {{ $image_resource = resources.Get (path.Join "media" $normalized) }} {{ end }} {{ if not $image_resource }} {{ $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 }} {{ $is_external := or (strings.HasPrefix $image_url "http://") (strings.HasPrefix $image_url "https://") }}
{{ end }} {{/* Avatar */}} {{ $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 }} {{ $status := $profile.status }} {{ if and $status (reflect.IsMap $status) }} {{ $status_icon_raw := index $status "icon" }} {{ if eq (printf "%T" $status_icon_raw) "string" }} {{ $status_icon = strings.TrimSpace $status_icon_raw }} {{ end }} {{ end }} {{ end }} {{ if $avatar }}
{{ $avatar_image := $avatar.Fill (printf "%sx%s Center" $generation_size $generation_size) }} {{$profile.title}} {{ with $status_icon }}{{ . | emojify }}{{ end }}
{{ end }} {{/* Name and Role - Centered */}}
{{/* 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 }} {{ $pronouns := "" }} {{ with $profile.pronouns }} {{ if eq (printf "%T" .) "string" }} {{ $pronouns = . }} {{ end }} {{ end }} {{ with $pronouns }}

({{ . }})

{{ end }} {{ $role_text := "" }} {{ with $profile.role }} {{ if eq (printf "%T" .) "string" }} {{ $role_text = . }} {{ end }} {{ end }} {{ with $role_text }}

{{ . | markdownify | emojify }}

{{ end }} {{ $affiliations_raw := $profile.affiliations }} {{ $affiliations := slice }} {{ if reflect.IsSlice $affiliations_raw }} {{ $affiliations = $affiliations_raw }} {{ else if eq (printf "%T" $affiliations_raw) "string" }} {{ $affiliations = slice $affiliations_raw }} {{ end }} {{ range $affiliations }} {{ $aff_name := "" }} {{ $aff_url := "" }} {{ if reflect.IsMap . }} {{ $nameRaw := index . "name" | default (index . "title") }} {{ if ne $nameRaw nil }} {{ $aff_name = printf "%v" $nameRaw }} {{ end }} {{ $urlRaw := index . "url" }} {{ if eq (printf "%T" $urlRaw) "string" }} {{ $aff_url = $urlRaw }} {{ end }} {{ else if eq (printf "%T" .) "string" }} {{ $aff_name = . }} {{ end }} {{ $aff_name = strings.TrimSpace $aff_name }} {{ $aff_url = strings.TrimSpace $aff_url }} {{ if $aff_name }}

{{ if $aff_url }} {{ $link := $aff_url }} {{ $scheme := (urls.Parse $link).Scheme }} {{ $target := "" }} {{ if not $scheme }} {{ if not (hasPrefix $link "#") }} {{ $link = $link | relLangURL }} {{ end }} {{ if eq (path.Ext $link) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }} {{ else if in (slice "http" "https") $scheme }} {{ $target = "target=\"_blank\" rel=\"noopener\"" }} {{ end }} {{ $aff_name }} {{ else }} {{ $aff_name }} {{ end }}

{{ end }} {{ end }}
{{/* Social Icons */}} {{ $links_raw := $profile.links }} {{ $links := slice }} {{ if reflect.IsSlice $links_raw }} {{ $links = $links_raw }} {{ else if eq (printf "%T" $links_raw) "string" }} {{ $links = slice $links_raw }} {{ end }} {{ if gt (len $links) 0 }}
{{ range $links }} {{ $linkUrl := "" }} {{ $iconName := "hero/link" }} {{ $linkLabel := "" }} {{ if reflect.IsMap . }} {{ $urlRaw := index . "url" | default (index . "link") }} {{ if eq (printf "%T" $urlRaw) "string" }} {{ $linkUrl = $urlRaw }} {{ end }} {{ $iconRaw := index . "icon" }} {{ if eq (printf "%T" $iconRaw) "string" }} {{ $iconName = $iconRaw }} {{ end }} {{ $labelRaw := index . "label" }} {{ if eq (printf "%T" $labelRaw) "string" }} {{ $linkLabel = $labelRaw }} {{ end }} {{ else if eq (printf "%T" .) "string" }} {{ $linkUrl = . }} {{ end }} {{ $linkUrl = strings.TrimSpace $linkUrl }} {{ if $linkUrl }} {{ $scheme := (urls.Parse $linkUrl).Scheme }} {{ $target := "" }} {{ if not $scheme }} {{ if not (hasPrefix $linkUrl "#") }} {{ $linkUrl = $linkUrl | relLangURL }} {{ end }} {{ if eq (path.Ext $linkUrl) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }} {{ else if in (slice "http" "https") $scheme }} {{ $target = "target=\"_blank\" rel=\"noopener\"" }} {{ end }} {{ partial "functions/get_icon" (dict "name" $iconName "attributes" "class=\"w-6 h-6\"") }} {{ end }} {{ end }}
{{ end }}
{{/* Right Column: Flexible span */}}
{{/* Bio Section */}} {{ $bio_content := "" }} {{ $bio_override_raw := index $content "text" }} {{ if ne $bio_override_raw nil }} {{ $bio_content = printf "%v" $bio_override_raw | emojify | $page.RenderString }} {{ end }} {{ if not $bio_content }} {{ with $profile.bio }}{{ $bio_content = printf "%v" . | emojify | $page.RenderString }}{{ end }} {{ end }} {{ with $bio_content }}
{{ partial "functions/get_icon" (dict "name" "identification" "attributes" "class='w-6 h-6 text-primary-600 dark:text-primary-400'") }}
{{ $i18n_about := i18n "about_me" }} {{ $about_default := cond (eq $i18n_about "about_me") "Professional Summary" $i18n_about }} {{ $about_heading := $about_default }} {{ $about_heading_raw := index $headings "about" }} {{ if eq (printf "%T" $about_heading_raw) "string" }} {{ $about_heading_raw = strings.TrimSpace $about_heading_raw }} {{ if ne $about_heading_raw "" }} {{ $about_heading = $about_heading_raw }} {{ end }} {{ end }}

{{ $about_heading }}

{{ . }}
{{ end }} {{/* CV Download Button */}} {{ $button_raw := index $content "button" }} {{ if and $button_raw (reflect.IsMap $button_raw) }} {{ $button_text := "" }} {{ $button_url := "" }} {{ with index $button_raw "text" }}{{ $button_text = printf "%v" . }}{{ end }} {{ with index $button_raw "url" }}{{ $button_url = printf "%v" . }}{{ end }} {{ $button_text = strings.TrimSpace $button_text }} {{ $button_url = strings.TrimSpace $button_url }} {{ if and $button_text $button_url }} {{ $button_link := $button_url }} {{ $scheme := (urls.Parse $button_link).Scheme }} {{ $target := "" }} {{ if not $scheme }} {{ if not (hasPrefix $button_link "#") }} {{ $button_link = $button_link | relLangURL }} {{ end }} {{ if eq (path.Ext $button_link) ".pdf" }}{{ $target = "target=\"_blank\" rel=\"noopener\"" }}{{ end }} {{ else if in (slice "http" "https") $scheme }} {{ $target = "target=\"_blank\" rel=\"noopener\"" }} {{ end }} {{ end }} {{ end }} {{/* Education Section */}} {{ $education_raw := $profile.education }} {{ $education := slice }} {{ if reflect.IsSlice $education_raw }} {{ $education = $education_raw }} {{ end }} {{ if gt (len $education) 0 }}
{{ partial "functions/get_icon" (dict "name" "academic-cap" "attributes" "class='w-6 h-6 text-primary-600 dark:text-primary-400'") }}
{{ $education_heading := i18n "education" }} {{ $education_heading_raw := index $headings "education" }} {{ if eq (printf "%T" $education_heading_raw) "string" }} {{ $education_heading_raw = strings.TrimSpace $education_heading_raw }} {{ if ne $education_heading_raw "" }} {{ $education_heading = $education_heading_raw }} {{ end }} {{ end }}

{{ $education_heading | markdownify }}

{{ range $education }} {{ if reflect.IsMap . }} {{ $degree := "" }} {{ $degreeRaw := index . "degree" | default (index . "area") }} {{ if ne $degreeRaw nil }}{{ $degree = printf "%v" $degreeRaw }}{{ end }} {{ $year := "" }} {{ with index . "year" }}{{ $year = printf "%v" . }}{{ end }} {{ $start := "" }} {{ with index . "start" }}{{ $start = printf "%v" . }}{{ end }} {{ $end := "" }} {{ with index . "end" }}{{ $end = printf "%v" . }}{{ end }} {{ $institution := "" }} {{ with index . "institution" }}{{ $institution = printf "%v" . }}{{ end }} {{ $icon := "" }} {{ $iconRaw := index . "icon" }} {{ if eq (printf "%T" $iconRaw) "string" }} {{ $icon = $iconRaw }} {{ end }}
{{ if $icon }} {{ partial "functions/get_icon" (dict "name" $icon "attributes" "class='w-6 h-6 text-primary-600 dark:text-primary-400'") }} {{ else }} {{ partial "functions/get_icon" (dict "name" "academic-cap" "attributes" "class='w-6 h-6 text-primary-600 dark:text-primary-400'") }} {{ end }}
{{ if $degree }}

{{ $degree }}

{{ end }} {{ if $year }}

{{ $year }}

{{ else if $start }}

{{ $start }} {{ if $end }}
{{ $end }}{{ end }}

{{ end }} {{ if $institution }}

{{ $institution }}

{{ end }}
{{ end }} {{ end }}
{{ end }} {{/* Interests Section */}} {{ $interests_raw := $profile.interests }} {{ $interests := slice }} {{ if reflect.IsSlice $interests_raw }} {{ $interests = $interests_raw }} {{ else if eq (printf "%T" $interests_raw) "string" }} {{ $interests = slice $interests_raw }} {{ end }} {{ if gt (len $interests) 0 }}
{{ partial "functions/get_icon" (dict "name" "sparkles" "attributes" "class='w-6 h-6 text-primary-600 dark:text-primary-400'") }}
{{ $interests_heading := i18n "interests" }} {{ $interests_heading_raw := index $headings "interests" }} {{ if eq (printf "%T" $interests_heading_raw) "string" }} {{ $interests_heading_raw = strings.TrimSpace $interests_heading_raw }} {{ if ne $interests_heading_raw "" }} {{ $interests_heading = $interests_heading_raw }} {{ end }} {{ end }}

{{ $interests_heading | markdownify }}

{{ range $interests }} {{ $interest := strings.TrimSpace (printf "%v" .) }} {{ if $interest }} {{ $interest | markdownify | emojify }} {{ end }} {{ end }}
{{ end }}