From 09eb7f7b184e9eed3c2ab37fdbd75b9f67d38460 Mon Sep 17 00:00:00 2001 From: George Cushen Date: Wed, 7 Jan 2026 19:18:50 +0000 Subject: [PATCH] feat: harden block inputs (batch 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finished hardening the remaining blocks by guarding content/design maps, normalizing list inputs, coercing numeric/boolean values, and sanitizing links; also tightened scroll target handling in block.html. Changes Normalized portfolio tags/tech stacks/links, made archive defaults safe, and ensured filter JS uses JSON-safe tags in block.html. Validated research area layouts and item fields, added safe media/link handling, and made CTA rendering resilient in block.html. Hardened resume blocks for profile fields, buttons/links, and dates using try with time in block.html, block.html, and block.html. Improved numeric parsing and labeling for language/skill meters in block.html and block.html. Added guarded items and predictable grid classes in block.html. Sanitized badge/title/suggestions/stats rendering in block.html, normalized tech categories and made list style exclusive in block.html, and hardened testimonials’ items/image handling in block.html. Normalized dynamic/static question data, badges, and safe links in block.html. --- modules/blox/blox/contact-info/block.html | 313 ++++++++++++++--- modules/blox/blox/cta-button-list/block.html | 74 +++- .../blox/blox/cta-image-paragraph/block.html | 76 ++++- modules/blox/blox/dev-hero/block.html | 318 ++++++++++++++---- modules/blox/blox/faq/block.html | 93 +++-- modules/blox/blox/features/block.html | 29 +- modules/blox/blox/hero/block.html | 80 +++-- .../blox/blox/knowledge-categories/block.html | 106 ++++-- modules/blox/blox/logos/block.html | 146 ++++++-- modules/blox/blox/portfolio/block.html | 305 +++++++++++++---- modules/blox/blox/research-areas/block.html | 257 +++++++++++--- modules/blox/blox/resume-awards/block.html | 146 ++++++-- modules/blox/blox/resume-biography/block.html | 283 ++++++++++++---- .../blox/blox/resume-experience/block.html | 287 +++++++++++++--- modules/blox/blox/resume-languages/block.html | 93 +++-- modules/blox/blox/resume-skills/block.html | 114 +++++-- modules/blox/blox/search-hero/block.html | 90 ++++- modules/blox/blox/stats/block.html | 123 +++++-- modules/blox/blox/tech-stack/block.html | 96 +++++- modules/blox/blox/testimonials/block.html | 63 +++- .../blox/blox/trending-questions/block.html | 242 ++++++++++--- 21 files changed, 2686 insertions(+), 648 deletions(-) diff --git a/modules/blox/blox/contact-info/block.html b/modules/blox/blox/contact-info/block.html index f80b049c..7c9af796 100644 --- a/modules/blox/blox/contact-info/block.html +++ b/modules/blox/blox/contact-info/block.html @@ -5,23 +5,200 @@ {{/* 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 }} {{/* Enable Alpine.js for copy-to-clipboard functionality */}} {{ $page.Store.Set "has_alpine" true }} -{{ $title := $block.content.title | default (i18n "block_contact_title" | default "Contact Us") | emojify | $page.RenderString }} -{{ $subtitle := $block.content.subtitle | emojify | $page.RenderString }} +{{ $default_title := i18n "block_contact_title" | default "Contact Us" }} +{{ $title := $default_title }} +{{ $title_raw := index $content "title" }} +{{ if eq (printf "%T" $title_raw) "string" }} + {{ $title_raw = strings.TrimSpace $title_raw }} + {{ if ne $title_raw "" }} + {{ $title = $title_raw }} + {{ end }} +{{ end }} +{{ $title = $title | emojify | $page.RenderString }} + +{{ $subtitle := "" }} +{{ $subtitle_raw := index $content "subtitle" }} +{{ if eq (printf "%T" $subtitle_raw) "string" }} + {{ $subtitle = $subtitle_raw | emojify | $page.RenderString }} +{{ end }} + +{{ $visit_title := i18n "block_contact_visit_title" | default "Visit Us" }} +{{ $visit_title_raw := index $content "visit_title" }} +{{ if eq (printf "%T" $visit_title_raw) "string" }} + {{ $visit_title_raw = strings.TrimSpace $visit_title_raw }} + {{ if ne $visit_title_raw "" }} + {{ $visit_title = $visit_title_raw }} + {{ end }} +{{ end }} + +{{ $connect_title_raw := "" }} +{{ $connect_title_value := index $content "connect_title" }} +{{ if eq (printf "%T" $connect_title_value) "string" }} + {{ $connect_title_raw = strings.TrimSpace $connect_title_value }} +{{ end }} +{{ $connect_title_standard := $connect_title_raw | default (i18n "block_contact_connect_title" | default "Connect") }} +{{ $connect_title_single := $connect_title_raw | default (i18n "block_contact_connect_title" | default "Let's Connect") }} + +{{ $connect_text := "" }} +{{ $connect_text_raw := index $content "text" }} +{{ if eq (printf "%T" $connect_text_raw) "string" }} + {{ $connect_text = strings.TrimSpace $connect_text_raw }} +{{ end }} +{{ if not $connect_text }} + {{ $connect_text = "I'm always open to discussing new projects, opportunities, or just having a chat." }} +{{ end }} + +{{ $address_lines := slice }} +{{ $address_raw := index $content "address" }} +{{ if and $address_raw (reflect.IsMap $address_raw) }} + {{ $lines_raw := index $address_raw "lines" }} + {{ if reflect.IsSlice $lines_raw }} + {{ range $lines_raw }} + {{ $line := strings.TrimSpace (printf "%v" .) }} + {{ if $line }}{{ $address_lines = $address_lines | append $line }}{{ end }} + {{ end }} + {{ else if eq (printf "%T" $lines_raw) "string" }} + {{ $line := strings.TrimSpace $lines_raw }} + {{ if $line }}{{ $address_lines = slice $line }}{{ end }} + {{ end }} +{{ else if eq (printf "%T" $address_raw) "string" }} + {{ $line := strings.TrimSpace $address_raw }} + {{ if $line }}{{ $address_lines = slice $line }}{{ end }} +{{ end }} + +{{ $office_hours := slice }} +{{ $office_raw := index $content "office_hours" }} +{{ if reflect.IsSlice $office_raw }} + {{ range $office_raw }} + {{ $line := strings.TrimSpace (printf "%v" .) }} + {{ if $line }}{{ $office_hours = $office_hours | append $line }}{{ end }} + {{ end }} +{{ else if eq (printf "%T" $office_raw) "string" }} + {{ $line := strings.TrimSpace $office_raw }} + {{ if $line }}{{ $office_hours = slice $line }}{{ end }} +{{ end }} + +{{ $map_url := "" }} +{{ $map_url_raw := index $content "map_url" }} +{{ if eq (printf "%T" $map_url_raw) "string" }} + {{ $map_url = strings.TrimSpace $map_url_raw }} +{{ end }} + +{{ $map_embed := "" }} +{{ $map_embed_raw := index $content "map_embed" }} +{{ if eq (printf "%T" $map_embed_raw) "string" }} + {{ $map_embed = $map_embed_raw }} +{{ end }} + +{{ $show_form := partial "functions/coerce_bool" (dict "value" (index $content "show_form") "default" false) }} +{{ $form_action := "" }} +{{ $form_action_raw := index $content "form_action" }} +{{ if eq (printf "%T" $form_action_raw) "string" }} + {{ $form_action = strings.TrimSpace $form_action_raw }} +{{ end }} +{{ if not $form_action }}{{ $form_action = "#" }}{{ end }} {{/* Check if Visit Us card has content */}} -{{ $has_visit_content := or $block.content.address $block.content.office_hours $block.content.map_url }} +{{ $has_visit_content := or (gt (len $address_lines) 0) (gt (len $office_hours) 0) $map_url }} {{/* Check if Connect card has content - fallback to author profile if no email/social */}} -{{ $author := $block.content.username | default "me" }} +{{ $author := "me" }} +{{ $author_raw := index $content "username" }} +{{ if eq (printf "%T" $author_raw) "string" }} + {{ $author = strings.TrimSpace $author_raw }} +{{ end }} {{ $profile := partial "functions/get_author_profile" $author }} -{{ $email := $block.content.email | default $profile.email }} -{{ $phone := $block.content.phone }} -{{ $social := $block.content.social | default $profile.links }} -{{ $has_connect_content := or $email $phone $social $block.content.prospective }} +{{ $author_data := index site.Data.authors (urlize $author) }} +{{ $email := "" }} +{{ $email_raw := index $content "email" }} +{{ if eq (printf "%T" $email_raw) "string" }} + {{ $email = strings.TrimSpace $email_raw }} +{{ end }} +{{ if and (not $email) $author_data (reflect.IsMap $author_data) }} + {{ $author_email_raw := index $author_data "email" }} + {{ if eq (printf "%T" $author_email_raw) "string" }} + {{ $email = strings.TrimSpace $author_email_raw }} + {{ end }} +{{ end }} + +{{ $phone := "" }} +{{ $phone_raw := index $content "phone" }} +{{ if eq (printf "%T" $phone_raw) "string" }} + {{ $phone = strings.TrimSpace $phone_raw }} +{{ end }} +{{ if and (not $phone) $author_data (reflect.IsMap $author_data) }} + {{ $author_phone_raw := index $author_data "phone" }} + {{ if eq (printf "%T" $author_phone_raw) "string" }} + {{ $phone = strings.TrimSpace $author_phone_raw }} + {{ end }} +{{ end }} + +{{ $social_raw := index $content "social" }} +{{ if eq $social_raw nil }}{{ $social_raw = $profile.links }}{{ end }} +{{ $social := slice }} +{{ if reflect.IsSlice $social_raw }} + {{ range $social_raw }} + {{ $url := "" }} + {{ $icon := "hero/link" }} + {{ $label := "" }} + {{ if reflect.IsMap . }} + {{ $url_raw := index . "url" | default (index . "link") }} + {{ if eq (printf "%T" $url_raw) "string" }} + {{ $url = strings.TrimSpace $url_raw }} + {{ end }} + {{ $icon_raw := index . "icon" }} + {{ if eq (printf "%T" $icon_raw) "string" }} + {{ $icon = $icon_raw }} + {{ end }} + {{ $label_raw := index . "label" | default (index . "name") }} + {{ if eq (printf "%T" $label_raw) "string" }} + {{ $label = $label_raw }} + {{ end }} + {{ else if eq (printf "%T" .) "string" }} + {{ $url = strings.TrimSpace . }} + {{ end }} + {{ if $url }} + {{ $social = $social | append (dict "url" $url "icon" $icon "label" $label) }} + {{ end }} + {{ end }} +{{ else if eq (printf "%T" $social_raw) "string" }} + {{ $url := strings.TrimSpace $social_raw }} + {{ if $url }} + {{ $social = slice (dict "url" $url "icon" "hero/link" "label" "") }} + {{ end }} +{{ end }} + +{{ $prospective_raw := index $content "prospective" }} +{{ $prospective := dict }} +{{ if and $prospective_raw (reflect.IsMap $prospective_raw) }} + {{ $prospective = $prospective_raw }} +{{ end }} +{{ $prospective_title := "" }} +{{ $prospective_title_raw := index $prospective "title" }} +{{ if eq (printf "%T" $prospective_title_raw) "string" }} + {{ $prospective_title = strings.TrimSpace $prospective_title_raw }} +{{ end }} +{{ $prospective_text := "" }} +{{ $prospective_text_raw := index $prospective "text" }} +{{ if eq (printf "%T" $prospective_text_raw) "string" }} + {{ $prospective_text = strings.TrimSpace $prospective_text_raw }} +{{ end }} +{{ $prospective_button := index $prospective "button" }} +{{ if not (reflect.IsMap $prospective_button) }}{{ $prospective_button = dict }}{{ end }} +{{ $prospective_button_text := "" }} +{{ with index $prospective_button "text" }}{{ $prospective_button_text = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $prospective_button_url := "" }} +{{ with index $prospective_button "url" }}{{ $prospective_button_url = strings.TrimSpace (printf "%v" .) }}{{ end }} + +{{ $has_connect_content := or $email $phone (gt (len $social) 0) $prospective_title $prospective_text $prospective_button_text $prospective_button_url }} {{/* Determine grid layout - single column centered if only one card */}} {{ $grid_class := "grid-cols-1 lg:grid-cols-2" }} @@ -65,32 +242,42 @@ {{ partial "functions/get_icon" (dict "name" "hero/map-pin" "attributes" "class=\"w-6 h-6 text-primary-600 dark:text-primary-400\"") }}

- {{ $block.content.visit_title | default (i18n "block_contact_visit_title" | default "Visit Us") }} + {{ $visit_title }}

- {{ with $block.content.address }} + {{ if gt (len $address_lines) 0 }}
- {{ range .lines }} + {{ range $address_lines }}

{{ . }}

{{ end }}
{{ end }} - {{ with $block.content.office_hours }} + {{ if gt (len $office_hours) 0 }}

{{ i18n "block_contact_office_hours" | default "Office Hours" }}

- {{ range . }} + {{ range $office_hours }}

{{ . }}

{{ end }}
{{ end }} - {{ with $block.content.map_url }} - {{ partial "functions/get_icon" (dict "name" "hero/map" "attributes" "class=\"w-5 h-5 mr-2\"") }} {{ i18n "block_contact_view_on_map" | default "View on Map" }} @@ -107,7 +294,8 @@ {{/* Filter social links - remove mailto if email is shown separately */}} {{ $filtered_social := slice }} {{ range $social }} - {{ if not (hasPrefix .url "mailto:") }} + {{ $url := index . "url" }} + {{ if and $url (not (and $email (hasPrefix $url "mailto:"))) }} {{ $filtered_social = $filtered_social | append . }} {{ end }} {{ end }} @@ -120,10 +308,10 @@

- {{ $block.content.connect_title | default (i18n "block_contact_connect_title" | default "Let's Connect") }} + {{ $connect_title_single }}

- {{ $block.content.text | default "I'm always open to discussing new projects, opportunities, or just having a chat." }} + {{ $connect_text }}

@@ -131,7 +319,7 @@ {{/* Email with click-to-copy */}}
{{/* Right: Social Links */}} - {{ with $filtered_social }} + {{ if gt (len $filtered_social) 0 }}

{{ i18n "block_contact_follow_me" | default "Find me on" }}

- {{ range . }} - + {{ if $social_label }}title="{{ $social_label }}"{{ end }}>
- {{ partial "functions/get_icon" (dict "name" .icon "attributes" "class=\"w-7 h-7\"") }} + {{ partial "functions/get_icon" (dict "name" $social_icon "attributes" "class=\"w-7 h-7\"") }}
{{ end }} @@ -204,7 +405,7 @@ {{ partial "functions/get_icon" (dict "name" "hero/chat-bubble-left-right" "attributes" "class=\"w-6 h-6 text-primary-600 dark:text-primary-400\"") }}

- {{ $block.content.connect_title | default (i18n "block_contact_connect_title" | default "Connect") }} + {{ $connect_title_standard }}

@@ -212,7 +413,7 @@ {{/* Contact Methods */}}
{{ with $email }} - +
{{ partial "functions/get_icon" (dict "name" "hero/envelope" "attributes" "class=\"w-5 h-5 text-primary-600 dark:text-primary-400\"") }}
@@ -224,7 +425,7 @@ {{ end }} {{ with $phone }} -
+
{{ partial "functions/get_icon" (dict "name" "hero/phone" "attributes" "class=\"w-5 h-5 text-primary-600 dark:text-primary-400\"") }}
@@ -236,15 +437,28 @@ {{ end }} {{/* Social Media */}} - {{ with $filtered_social }} + {{ if gt (len $filtered_social) 0 }}

{{ i18n "block_contact_follow_me" | default "Find me on" }}

@@ -255,15 +469,28 @@ {{ end }} {{/* Prospective Members - shown in both layouts */}} - {{ with $block.content.prospective }} + {{ if or $prospective_title $prospective_text $prospective_button_text $prospective_button_url }} + {{ $prospective_heading := $prospective_title | default (i18n "block_contact_prospective_title" | default "Prospective Members") }} @@ -273,7 +500,7 @@
{{/* Optional Map Embed */}} - {{ with $block.content.map_embed }} + {{ with $map_embed }}
{{ . | safeHTML }} @@ -282,11 +509,11 @@ {{ end }} {{/* Contact Form (optional) */}} - {{ if $block.content.show_form }} + {{ if $show_form }}

{{ i18n "block_contact_form_title" | default "Send us a Message" }}

-
+
diff --git a/modules/blox/blox/cta-button-list/block.html b/modules/blox/blox/cta-button-list/block.html index 78d72e37..fb1efbeb 100644 --- a/modules/blox/blox/cta-button-list/block.html +++ b/modules/blox/blox/cta-button-list/block.html @@ -5,22 +5,70 @@ {{/* Initialise */}} {{ $page := .wcPage }} {{ $block := .wcBlock }} +{{ $content := $block.content }} +{{ if not (reflect.IsMap $content) }}{{ $content = dict }}{{ end }}
-{{ range $index, $item := $block.content.buttons }} - -
-
- {{ with .icon }} - {{ partial "functions/get_icon" (dict "name" . "attributes" "height=\"40\" width=\"40\" class=\"rounded-sm\"") }} +{{ $buttons_raw := index $content "buttons" }} +{{ $buttons := slice }} +{{ if reflect.IsSlice $buttons_raw }} + {{ $buttons = $buttons_raw }} +{{ else if and $buttons_raw (reflect.IsMap $buttons_raw) }} + {{ $buttons = slice $buttons_raw }} +{{ else if eq (printf "%T" $buttons_raw) "string" }} + {{ $buttons = slice (dict "url" $buttons_raw) }} +{{ end }} + +{{ range $index, $item := $buttons }} + {{ $text := "" }} + {{ $url := "" }} + {{ $icon := "" }} + {{ $new_tab := false }} + {{ if reflect.IsMap $item }} + {{ $text_raw := index $item "text" | default (index $item "label") | default (index $item "name") }} + {{ if ne $text_raw nil }}{{ $text = strings.TrimSpace (printf "%v" $text_raw) }}{{ end }} + {{ $url_raw := index $item "url" | default (index $item "link") }} + {{ if eq (printf "%T" $url_raw) "string" }}{{ $url = strings.TrimSpace $url_raw }}{{ end }} + {{ $icon_raw := index $item "icon" }} + {{ if eq (printf "%T" $icon_raw) "string" }}{{ $icon = $icon_raw }}{{ end }} + {{ $new_tab = partial "functions/coerce_bool" (dict "value" (index $item "new_tab") "default" false) }} + {{ else if eq (printf "%T" $item) "string" }} + {{ $url = strings.TrimSpace $item }} + {{ end }} + {{ if and (not $text) $url }} + {{ $text = $url }} + {{ end }} + {{ if $url }} + {{ $link := $url }} + {{ $target := "" }} + {{ $scheme := (urls.Parse $link).Scheme }} + {{ if not $scheme }} + {{ if not (hasPrefix $link "#") }} + {{ $link = $link | relLangURL }} {{ end }} -
-
- {{ .text | markdownify | emojify }} -
-
-
-{{end}} + {{ if eq (path.Ext $link) ".pdf" }} + {{ $new_tab = true }} + {{ end }} + {{ else if in (slice "http" "https") $scheme }} + {{ $new_tab = true }} + {{ end }} + {{ if $new_tab }} + {{ $target = "target=\"_blank\" rel=\"noopener noreferrer\"" }} + {{ end }} + +
+
+ {{ with $icon }} + {{ partial "functions/get_icon" (dict "name" . "attributes" "height=\"40\" width=\"40\" class=\"rounded-sm\"") }} + {{ end }} +
+
+ {{ $text | markdownify | emojify }} +
+
+
+ {{ end }} +{{ end }}
diff --git a/modules/blox/blox/cta-image-paragraph/block.html b/modules/blox/blox/cta-image-paragraph/block.html index c4186b5f..03901651 100644 --- a/modules/blox/blox/cta-image-paragraph/block.html +++ b/modules/blox/blox/cta-image-paragraph/block.html @@ -5,14 +5,34 @@ {{/* Initialise */}} {{ $page := .wcPage }} {{ $block := .wcBlock }} +{{ $content := $block.content }} +{{ if not (reflect.IsMap $content) }}{{ $content = dict }}{{ end }}
- {{ range $idx, $item := $block.content.items }} - {{ $title := .title | emojify | $page.RenderString }} - {{ $text := .text | emojify | $page.RenderString }} - {{ $image_path := path.Join "media" .image }} - {{ $image := resources.GetMatch $image_path }} - {{ with $image }} + {{ $items_raw := index $content "items" }} + {{ $items := slice }} + {{ if reflect.IsSlice $items_raw }} + {{ $items = $items_raw }} + {{ else if and $items_raw (reflect.IsMap $items_raw) }} + {{ $items = slice $items_raw }} + {{ end }} + + {{ range $idx, $item := $items }} + {{ if reflect.IsMap $item }} + {{ $title := "" }} + {{ $title_raw := index $item "title" }} + {{ if eq (printf "%T" $title_raw) "string" }}{{ $title = $title_raw | emojify | $page.RenderString }}{{ end }} + {{ $text := "" }} + {{ $text_raw := index $item "text" }} + {{ if eq (printf "%T" $text_raw) "string" }}{{ $text = $text_raw | emojify | $page.RenderString }}{{ end }} + {{ $image_name := "" }} + {{ $image_raw := index $item "image" }} + {{ if eq (printf "%T" $image_raw) "string" }}{{ $image_name = strings.TrimSpace $image_raw }}{{ end }} + {{ $image_path := "" }} + {{ if $image_name }}{{ $image_path = path.Join "media" $image_name }}{{ end }} + {{ $image := "" }} + {{ if $image_path }}{{ $image = resources.GetMatch $image_path }}{{ end }} + {{ if $image }}
{{ if ne $image.MediaType.SubType "gif" }} {{ $responsive := partial "functions/process_responsive_image.html" (dict @@ -35,29 +55,57 @@ alt="{{$title | plainify}}" {{ if (modBool $idx 2)}}style="order: 1"{{end}}> {{ end }} {{ else }} - {{ errorf "%s uses the `cta-image-paragraph` blox which specifies a non-existent `image` at `assets/%s`. Please add the image to this folder and try again." $page.File.Path $image_path }} + {{ warnf "%s uses the `cta-image-paragraph` blox which specifies a non-existent `image` at `assets/%s`. Skipping this item." $page.File.Path $image_path }} {{ end }}

{{$title}}

{{$text}}

- {{ $icon := .feature_icon | default "check" }} - {{ if .features }} + {{ $icon := "check" }} + {{ $icon_raw := index $item "feature_icon" }} + {{ if eq (printf "%T" $icon_raw) "string" }}{{ $icon = $icon_raw }}{{ end }} + {{ $features_raw := index $item "features" }} + {{ $features := slice }} + {{ if reflect.IsSlice $features_raw }} + {{ $features = $features_raw }} + {{ else if eq (printf "%T" $features_raw) "string" }} + {{ $features = slice $features_raw }} + {{ end }} + {{ if gt (len $features) 0 }}
    - {{ range .features }} + {{ range $features }}
  • {{ partial "functions/get_icon" (dict "name" $icon "attributes" `class="inline-block pr-3" style="height: 1em;"`) }} - {{ . | markdownify }} + {{ printf "%v" . | markdownify }}
  • {{ end }}
{{ end }} - {{ with .button }} - - {{.text}} + {{ $button_raw := index $item "button" }} + {{ if and $button_raw (reflect.IsMap $button_raw) }} + {{ $button_text := "" }} + {{ $button_url := "" }} + {{ with index $button_raw "text" }}{{ $button_text = strings.TrimSpace (printf "%v" .) }}{{ end }} + {{ with index $button_raw "url" }}{{ $button_url = strings.TrimSpace (printf "%v" .) }}{{ end }} + {{ if and $button_text $button_url }} + {{ $link := $button_url }} + {{ $target := "" }} + {{ $scheme := (urls.Parse $link).Scheme }} + {{ 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 }} + + {{ $button_text }} {{ end }} + {{ end }}
{{ end }} + {{ end }}
diff --git a/modules/blox/blox/dev-hero/block.html b/modules/blox/blox/dev-hero/block.html index 1d4a83b3..3f1be5f4 100644 --- a/modules/blox/blox/dev-hero/block.html +++ b/modules/blox/blox/dev-hero/block.html @@ -5,28 +5,146 @@ {{/* 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 }} {{/* Enable animations if typewriter or scroll animations are configured */}} -{{ $typewriter := $block.content.typewriter | default dict }} -{{ $has_animations := or $typewriter.enable $block.design.animations }} +{{ $typewriter := index $content "typewriter" }} +{{ if not (reflect.IsMap $typewriter) }}{{ $typewriter = dict }}{{ end }} +{{ $typewriter_enabled := partial "functions/coerce_bool" (dict "value" (index $typewriter "enable") "default" false) }} +{{ $animations_enabled := partial "functions/coerce_bool" (dict "value" (index $design "animations") "default" false) }} +{{ $has_animations := or $typewriter_enabled $animations_enabled }} {{ if $has_animations }} {{ $page.Store.Set "has_animations" true }} {{ $page.Store.Set "has_alpine" true }} {{ end }} {{/* Get author data from YAML */}} -{{ $username := $block.content.username | default "me" }} +{{ $username := "me" }} +{{ $username_raw := index $content "username" }} +{{ if eq (printf "%T" $username_raw) "string" }} + {{ $username = strings.TrimSpace $username_raw }} +{{ end }} {{ $author := partial "functions/get_author_profile" $username }} {{/* Get avatar */}} {{ $avatar := "" }} -{{ $avatar_shape := $block.design.avatar_shape | default "circle" }} +{{ $avatar_shape := "circle" }} +{{ $avatar_shape_raw := index $design "avatar_shape" }} +{{ if eq (printf "%T" $avatar_shape_raw) "string" }} + {{ $avatar_shape = lower (strings.TrimSpace $avatar_shape_raw) }} +{{ end }} {{ with $author.avatar }} {{ $avatar = .Fill "300x300 webp Center" }} {{ end }} {{/* Layout style */}} -{{ $style := $block.design.style | default "centered" }} +{{ $style := "centered" }} +{{ $style_raw := index $design "style" }} +{{ if eq (printf "%T" $style_raw) "string" }} + {{ $style_candidate := lower (strings.TrimSpace $style_raw) }} + {{ if in (slice "centered" "split") $style_candidate }} + {{ $style = $style_candidate }} + {{ end }} +{{ end }} + +{{ $show_status := partial "functions/coerce_bool" (dict "value" (index $content "show_status") "default" false) }} +{{ $show_scroll := partial "functions/coerce_bool" (dict "value" (index $content "show_scroll_indicator") "default" false) }} + +{{ $scroll_target := "#projects" }} +{{ $scroll_target_raw := index $content "scroll_target" }} +{{ if eq (printf "%T" $scroll_target_raw) "string" }} + {{ $scroll_target = strings.TrimSpace $scroll_target_raw }} +{{ end }} +{{ if not $scroll_target }}{{ $scroll_target = "#projects" }}{{ end }} + +{{ $greeting := "" }} +{{ $greeting_raw := index $content "greeting" }} +{{ if eq (printf "%T" $greeting_raw) "string" }}{{ $greeting = $greeting_raw }}{{ end }} +{{ $name_prefix := "" }} +{{ $name_prefix_raw := index $content "name_prefix" }} +{{ if eq (printf "%T" $name_prefix_raw) "string" }}{{ $name_prefix = $name_prefix_raw }}{{ end }} + +{{ $title_override := "" }} +{{ $title_raw := index $content "title" }} +{{ if eq (printf "%T" $title_raw) "string" }}{{ $title_override = strings.TrimSpace $title_raw }}{{ end }} + +{{ $tagline := "" }} +{{ $tagline_raw := index $content "tagline" }} +{{ if eq (printf "%T" $tagline_raw) "string" }}{{ $tagline = $tagline_raw }}{{ end }} + +{{ $bio_override := "" }} +{{ $bio_raw := index $content "bio" }} +{{ if eq (printf "%T" $bio_raw) "string" }}{{ $bio_override = $bio_raw }}{{ end }} + +{{ $role := $author.role | default $tagline }} +{{ $bio := $author.bio | default $bio_override }} + +{{ $typewriter_strings := slice }} +{{ $strings_raw := index $typewriter "strings" }} +{{ if reflect.IsSlice $strings_raw }} + {{ range $strings_raw }} + {{ $val := strings.TrimSpace (printf "%v" .) }} + {{ if $val }}{{ $typewriter_strings = $typewriter_strings | append $val }}{{ end }} + {{ end }} +{{ else if eq (printf "%T" $strings_raw) "string" }} + {{ $val := strings.TrimSpace $strings_raw }} + {{ if $val }}{{ $typewriter_strings = slice $val }}{{ end }} +{{ end }} + +{{ $typewriter_prefix := "" }} +{{ $typewriter_prefix_raw := index $typewriter "prefix" }} +{{ if eq (printf "%T" $typewriter_prefix_raw) "string" }}{{ $typewriter_prefix = $typewriter_prefix_raw }}{{ end }} +{{ $type_speed := partial "functions/coerce_int" (dict "value" (index $typewriter "type_speed") "default" 80 "min" 10 "max" 500) }} +{{ $delete_speed := partial "functions/coerce_int" (dict "value" (index $typewriter "delete_speed") "default" 50 "min" 10 "max" 500) }} +{{ $pause_time := partial "functions/coerce_int" (dict "value" (index $typewriter "pause_time") "default" 2000 "min" 200 "max" 10000) }} + +{{ $links_raw := $author.links | default (index $content "links") }} +{{ $links := slice }} +{{ if reflect.IsSlice $links_raw }} + {{ range $links_raw }} + {{ $url := "" }} + {{ $icon := "hero/link" }} + {{ $label := "" }} + {{ if reflect.IsMap . }} + {{ $url_raw := index . "url" | default (index . "link") }} + {{ if eq (printf "%T" $url_raw) "string" }}{{ $url = strings.TrimSpace $url_raw }}{{ end }} + {{ $icon_raw := index . "icon" }} + {{ if eq (printf "%T" $icon_raw) "string" }}{{ $icon = $icon_raw }}{{ end }} + {{ $label_raw := index . "label" | default (index . "name") }} + {{ if eq (printf "%T" $label_raw) "string" }}{{ $label = $label_raw }}{{ end }} + {{ else if eq (printf "%T" .) "string" }} + {{ $url = strings.TrimSpace . }} + {{ end }} + {{ if $url }} + {{ $links = $links | append (dict "url" $url "icon" $icon "label" $label) }} + {{ end }} + {{ end }} +{{ else if eq (printf "%T" $links_raw) "string" }} + {{ $url := strings.TrimSpace $links_raw }} + {{ if $url }} + {{ $links = slice (dict "url" $url "icon" "hero/link" "label" "") }} + {{ end }} +{{ end }} + +{{ $cta_buttons_raw := index $content "cta_buttons" }} +{{ $cta_buttons := slice }} +{{ if reflect.IsSlice $cta_buttons_raw }} + {{ $cta_buttons = $cta_buttons_raw }} +{{ else if and $cta_buttons_raw (reflect.IsMap $cta_buttons_raw) }} + {{ $cta_buttons = slice $cta_buttons_raw }} +{{ end }} + +{{ $status_icon := "" }} +{{ $status := $author.status }} +{{ if and $status (reflect.IsMap $status) }} + {{ $status_icon_raw := index $status "icon" }} + {{ if eq (printf "%T" $status_icon_raw) "string" }} + {{ $status_icon = $status_icon_raw }} + {{ end }} +{{ end }}
@@ -61,8 +179,8 @@ {{ $author.title }}
{{/* Status emoji badge */}} - {{ if $block.content.show_status }} - {{ with $author.status.icon }} + {{ if $show_status }} + {{ with $status_icon }} {{ . | emojify }} @@ -77,7 +195,7 @@ {{/* Content */}}
{{/* Greeting */}} - {{ with $block.content.greeting }} + {{ with $greeting }}

{{ . }} @@ -86,19 +204,18 @@ {{/* Name */}}

- {{ with $block.content.name_prefix }}{{ . }} {{ end }} + {{ with $name_prefix }}{{ . }} {{ end }} - {{ $author.title | default $block.content.title | default (i18n "developer" | default "Developer") }} + {{ $author.title | default $title_override | default (i18n "developer" | default "Developer") }}

{{/* Role/Tagline with optional typewriter */}} - {{ $role := $author.role | default $block.content.tagline }} - {{ if and $typewriter.enable $typewriter.strings }} + {{ if and $typewriter_enabled (gt (len $typewriter_strings) 0) }}

- {{ with $typewriter.prefix }}{{ . }} {{ end }} + {{ with $typewriter_prefix }}{{ . }} {{ end }} @@ -110,26 +227,34 @@ {{ end }} {{/* Bio */}} - {{ with $author.bio | default $block.content.bio }} + {{ with $bio }}

{{ . | $page.RenderString }}

{{ end }} {{/* Social Links */}} - {{ $links := $author.links | default $block.content.links }} - {{ with $links }} + {{ if gt (len $links) 0 }}
- {{ range . }} - {{ $icon := .icon | default "link" }} - {{ $url := .url }} + {{ range $links }} + {{ $icon := index . "icon" | default "hero/link" }} + {{ $url := index . "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 noreferrer\"" }} + {{ end }} {{ partial "functions/get_icon" (dict "name" $icon "attributes" "class=\"w-5 h-5\"") }} @@ -138,19 +263,45 @@ {{ end }} {{/* CTA Buttons */}} - {{ with $block.content.cta_buttons }} + {{ if gt (len $cta_buttons) 0 }}
- {{ range $idx, $btn := . }} + {{ range $idx, $btn := $cta_buttons }} + {{ if reflect.IsMap $btn }} {{ $is_primary := eq $idx 0 }} + {{ $btn_text := "" }} + {{ $btn_url := "" }} + {{ $btn_icon := "" }} + {{ $btn_new_tab := partial "functions/coerce_bool" (dict "value" (index $btn "new_tab") "default" false) }} + {{ with index $btn "text" }}{{ $btn_text = strings.TrimSpace (printf "%v" .) }}{{ end }} + {{ with index $btn "url" }}{{ $btn_url = strings.TrimSpace (printf "%v" .) }}{{ end }} + {{ with index $btn "icon" }}{{ $btn_icon = printf "%v" . }}{{ end }} + {{ if and $btn_text $btn_url }} + {{ $link := $btn_url }} + {{ $target := "" }} + {{ $scheme := (urls.Parse $link).Scheme }} + {{ if not $scheme }} + {{ if not (hasPrefix $link "#") }} + {{ $link = $link | relLangURL }} + {{ end }} + {{ if eq (path.Ext $link) ".pdf" }}{{ $btn_new_tab = true }}{{ end }} + {{ else if in (slice "http" "https") $scheme }} + {{ $btn_new_tab = true }} + {{ end }} + {{ if $btn_new_tab }} + {{ $target = "target=\"_blank\" rel=\"noopener\"" }} + {{ end }} - {{ with .icon }} - {{ partial "functions/get_icon" (dict "name" . "attributes" "class=\"w-5 h-5\"") }} + {{ if $btn_icon }} + {{ partial "functions/get_icon" (dict "name" $btn_icon "attributes" "class=\"w-5 h-5\"") }} {{ end }} - {{ .text }} + {{ $btn_text }} + {{ end }} + {{ end }} {{ end }}
{{ end }} @@ -168,8 +319,8 @@ {{ $author.title }}
{{/* Status emoji badge */}} - {{ if $block.content.show_status }} - {{ with $author.status.icon }} + {{ if $show_status }} + {{ with $status_icon }} {{ . | emojify }} @@ -180,7 +331,7 @@ {{ end }} {{/* Greeting */}} - {{ with $block.content.greeting }} + {{ with $greeting }}

{{ . }} @@ -190,19 +341,18 @@ {{/* Name */}}

- {{ with $block.content.name_prefix }}{{ . }} {{ end }} + {{ with $name_prefix }}{{ . }} {{ end }} - {{ $author.title | default $block.content.title | default (i18n "developer" | default "Developer") }} + {{ $author.title | default $title_override | default (i18n "developer" | default "Developer") }}

{{/* Role/Tagline with optional typewriter */}} - {{ $role := $author.role | default $block.content.tagline }} - {{ if and $typewriter.enable $typewriter.strings }} + {{ if and $typewriter_enabled (gt (len $typewriter_strings) 0) }}

- {{ with $typewriter.prefix }}{{ . }} {{ end }} + {{ with $typewriter_prefix }}{{ . }} {{ end }} @@ -214,26 +364,34 @@ {{ end }} {{/* Bio */}} - {{ with $author.bio | default $block.content.bio }} + {{ with $bio }}

{{ . | $page.RenderString }}

{{ end }} {{/* Social Links */}} - {{ $links := $author.links | default $block.content.links }} - {{ with $links }} + {{ if gt (len $links) 0 }}
- {{ range . }} - {{ $icon := .icon | default "link" }} - {{ $url := .url }} + {{ range $links }} + {{ $icon := index . "icon" | default "hero/link" }} + {{ $url := index . "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 noreferrer\"" }} + {{ end }} {{ partial "functions/get_icon" (dict "name" $icon "attributes" "class=\"w-5 h-5\"") }} @@ -242,19 +400,45 @@ {{ end }} {{/* CTA Buttons */}} - {{ with $block.content.cta_buttons }} + {{ if gt (len $cta_buttons) 0 }} {{ end }} @@ -262,10 +446,20 @@ {{ end }} {{/* Scroll indicator - clicks to scroll to next section */}} - {{ if $block.content.show_scroll_indicator }} - {{ $scroll_target := $block.content.scroll_target | default "#projects" }} + {{ if $show_scroll }} + {{ $scroll_link := $scroll_target }} + {{ $scroll_target_attr := "" }} + {{ $scroll_scheme := (urls.Parse $scroll_link).Scheme }} + {{ if not $scroll_scheme }} + {{ if not (hasPrefix $scroll_link "#") }} + {{ $scroll_link = $scroll_link | relLangURL }} + {{ end }} + {{ else if in (slice "http" "https") $scroll_scheme }} + {{ $scroll_target_attr = "target=\"_blank\" rel=\"noopener\"" }} + {{ end }} diff --git a/modules/blox/blox/faq/block.html b/modules/blox/blox/faq/block.html index 0a7c448b..97099d91 100644 --- a/modules/blox/blox/faq/block.html +++ b/modules/blox/blox/faq/block.html @@ -1,27 +1,64 @@ {{- $wcPage := .wcPage -}} {{- $wcBlock := .wcBlock -}} {{- $wcIdentifier := .wcIdentifier -}} +{{- $content := $wcBlock.content -}} +{{- if not (reflect.IsMap $content) }}{{ $content = dict }}{{ end -}} +{{- $design := $wcBlock.design -}} +{{- if not (reflect.IsMap $design) }}{{ $design = dict }}{{ end -}} {{/* Enable Alpine.js for interactive accordion */}} {{ $wcPage.Page.Store.Set "has_alpine" true }} -{{- $st := $wcBlock.design.spacing | default dict -}} -{{- $pad := $st.padding | default (slice "20px" "0" "20px" "0") -}} +{{- $st := index $design "spacing" -}} +{{- if not (reflect.IsMap $st) }}{{ $st = dict }}{{ end -}} +{{- $pad := slice "20px" "0" "20px" "0" -}} +{{- $pad_raw := index $st "padding" -}} +{{- if and (reflect.IsSlice $pad_raw) (ge (len $pad_raw) 4) }}{{ $pad = $pad_raw }}{{ end -}} {{- $pad_sm := slice "3rem" "0" -}} -{{- $mar := $st.margin | default (slice "0" "0" "0" "0") -}} +{{- $pad_sm_raw := index $st "padding_sm" -}} +{{- if and (reflect.IsSlice $pad_sm_raw) (ge (len $pad_sm_raw) 2) }}{{ $pad_sm = $pad_sm_raw }}{{ end -}} +{{- $mar := slice "0" "0" "0" "0" -}} +{{- $mar_raw := index $st "margin" -}} +{{- if and (reflect.IsSlice $mar_raw) (ge (len $mar_raw) 4) }}{{ $mar = $mar_raw }}{{ end -}} -{{- $bg := $wcBlock.design.background | default dict -}} -{{- $bg_color_val := $bg.color | default "" -}} +{{- $bg := index $design "background" -}} +{{- if not (reflect.IsMap $bg) }}{{ $bg = dict }}{{ end -}} +{{- $bg_color_val := "" -}} +{{- $bg_color_raw := index $bg "color" -}} +{{- if eq (printf "%T" $bg_color_raw) "string" }}{{ $bg_color_val = $bg_color_raw }}{{ end -}} + +{{- $title := "" -}} +{{- $title_raw := index $content "title" -}} +{{- if eq (printf "%T" $title_raw) "string" }}{{ $title = $title_raw }}{{ end -}} +{{- $subtitle := "" -}} +{{- $subtitle_raw := index $content "subtitle" -}} +{{- if eq (printf "%T" $subtitle_raw) "string" }}{{ $subtitle = $subtitle_raw }}{{ end -}} +{{- $text := "" -}} +{{- $text_raw := index $content "text" -}} +{{- if eq (printf "%T" $text_raw) "string" }}{{ $text = $text_raw }}{{ end -}} + +{{- $items_raw := index $content "items" -}} +{{- $items := slice -}} +{{- if reflect.IsSlice $items_raw }}{{ $items = $items_raw }}{{ end -}} + +{{- $button := index $content "button" -}} +{{- if not (reflect.IsMap $button) }}{{ $button = dict }}{{ end -}} +{{- $button_text := "" -}} +{{- with index $button "text" }}{{ $button_text = strings.TrimSpace (printf "%v" .) }}{{ end -}} +{{- $button_url := "" -}} +{{- with index $button "url" }}{{ $button_url = strings.TrimSpace (printf "%v" .) }}{{ end -}} +{{- $button_icon := "" -}} +{{- with index $button "icon" }}{{ $button_icon = printf "%v" . }}{{ end -}}
- {{- with $wcBlock.content.title -}} + {{- with $title -}}

{{ . | markdownify | emojify }}

- {{- with $wcBlock.content.subtitle -}} + {{- with $subtitle -}}

{{ . | markdownify | emojify }}

@@ -29,18 +66,24 @@
{{- end -}} - {{- with $wcBlock.content.text -}} + {{- with $text -}}
{{ . | markdownify | emojify }}
{{- end -}} - {{- $items := $wcBlock.content.items | default slice -}} - - {{- if $items -}} + {{- if gt (len $items) 0 -}}
{{- range $index, $item := $items -}} + {{- if reflect.IsMap $item -}} + {{- $question := "" -}} + {{- $question_raw := index $item "question" | default (index $item "title") -}} + {{- if ne $question_raw nil }}{{ $question = printf "%v" $question_raw }}{{ end -}} + {{- $answer := "" -}} + {{- $answer_raw := index $item "answer" | default (index $item "text") -}} + {{- if ne $answer_raw nil }}{{ $answer = printf "%v" $answer_raw }}{{ end -}} + {{- if or $question $answer -}}
{{- end -}} + {{- end -}} + {{- end -}}
{{- end -}} - {{- with $wcBlock.content.button -}} + {{- if and $button_text $button_url -}} + {{- $link := $button_url -}} + {{- $target := "" -}} + {{- $scheme := (urls.Parse $link).Scheme -}} + {{- 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 -}}
@@ -94,4 +150,3 @@
- diff --git a/modules/blox/blox/features/block.html b/modules/blox/blox/features/block.html index 66b7b0eb..012e9e1c 100644 --- a/modules/blox/blox/features/block.html +++ b/modules/blox/blox/features/block.html @@ -5,8 +5,15 @@ {{/* Initialise */}} {{ $page := .wcPage }} {{ $block := .wcBlock }} -{{ $title := $block.content.title | emojify | $page.RenderString }} -{{ $text := $block.content.text | emojify | $page.RenderString }} +{{ $content := $block.content }} +{{ if not (reflect.IsMap $content) }}{{ $content = dict }}{{ end }} +{{ $title := "" }} +{{ with index $content "title" }}{{ $title = printf "%v" . | emojify | $page.RenderString }}{{ end }} +{{ $text := "" }} +{{ with index $content "text" }}{{ $text = printf "%v" . | emojify | $page.RenderString }}{{ end }} +{{ $items_raw := index $content "items" }} +{{ $items := slice }} +{{ if reflect.IsSlice $items_raw }}{{ $items = $items_raw }}{{ end }}
@@ -19,16 +26,26 @@ {{ end }}
- {{ range $block.content.items }} + {{ range $items }} + {{ if reflect.IsMap . }} + {{ $icon := "" }} + {{ with index . "icon" }} + {{ if eq (printf "%T" .) "string" }}{{ $icon = . }}{{ end }} + {{ end }} + {{ $name := "" }} + {{ with index . "name" }}{{ $name = printf "%v" . }}{{ end }} + {{ $description := "" }} + {{ with index . "description" }}{{ $description = printf "%v" . }}{{ end }}
- {{ with .icon }} + {{ with $icon }}
{{ partial "functions/get_icon" (dict "name" . "attributes" `class="w-5 h-5 lg:w-6 lg:h-6"`) }}
{{ end }} -

{{ .name | $page.RenderString }}

-

{{ .description | $page.RenderString }}

+ {{ with $name }}

{{ . | $page.RenderString }}

{{ end }} + {{ with $description }}

{{ . | $page.RenderString }}

{{ end }}
+ {{ end }} {{ end }}
diff --git a/modules/blox/blox/hero/block.html b/modules/blox/blox/hero/block.html index 5b81fb38..b7ad8ea2 100644 --- a/modules/blox/blox/hero/block.html +++ b/modules/blox/blox/hero/block.html @@ -5,30 +5,56 @@ {{/* 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 }} +{{ $no_padding := partial "functions/coerce_bool" (dict "value" (index $design "no_padding") "default" false) }} + +{{ $announcement := index $content "announcement" }} +{{ if not (reflect.IsMap $announcement) }}{{ $announcement = dict }}{{ end }} +{{ $announcement_text := "" }} +{{ with index $announcement "text" }}{{ $announcement_text = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $announcement_link := index $announcement "link" }} +{{ if not (reflect.IsMap $announcement_link) }}{{ $announcement_link = dict }}{{ end }} +{{ $announcement_link_text := "" }} +{{ with index $announcement_link "text" }}{{ $announcement_link_text = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $announcement_link_url := "" }} +{{ with index $announcement_link "url" }}{{ $announcement_link_url = strings.TrimSpace (printf "%v" .) }}{{ end }} + +{{ $primary_action := index $content "primary_action" }} +{{ if not (reflect.IsMap $primary_action) }}{{ $primary_action = dict }}{{ end }} +{{ $primary_text := "" }} +{{ with index $primary_action "text" }}{{ $primary_text = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $primary_url := "" }} +{{ with index $primary_action "url" }}{{ $primary_url = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $primary_icon := "" }} +{{ with index $primary_action "icon" }}{{ $primary_icon = printf "%v" . }}{{ end }} + +{{ $secondary_action := index $content "secondary_action" }} +{{ if not (reflect.IsMap $secondary_action) }}{{ $secondary_action = dict }}{{ end }} +{{ $secondary_text := "" }} +{{ with index $secondary_action "text" }}{{ $secondary_text = strings.TrimSpace (printf "%v" .) }}{{ end }} +{{ $secondary_url := "" }} +{{ with index $secondary_action "url" }}{{ $secondary_url = strings.TrimSpace (printf "%v" .) }}{{ end }}
-
+
- {{ if $block.content.announcement.text }} - {{ $announcement := $block.content.announcement }} + {{ if $announcement_text }}