diff --git a/.github/workflows/ci-build-starters-matrix.yml b/.github/workflows/ci-build-starters-matrix.yml index c620a25d..ecdbfa6a 100644 --- a/.github/workflows/ci-build-starters-matrix.yml +++ b/.github/workflows/ci-build-starters-matrix.yml @@ -100,4 +100,4 @@ jobs: - name: Build ${{ matrix.starter.name }} working-directory: ${{ matrix.starter.path }} - run: hugo --minify + run: hugo --minify --panicOnWarning diff --git a/.github/workflows/ci-build-test-site.yml b/.github/workflows/ci-build-test-site.yml index fc7a857e..d7884a17 100644 --- a/.github/workflows/ci-build-test-site.yml +++ b/.github/workflows/ci-build-test-site.yml @@ -98,5 +98,5 @@ jobs: extended: true - name: Build - run: hugo --minify --templateMetrics --templateMetricsHints + run: hugo --minify --panicOnWarning --templateMetrics --templateMetricsHints working-directory: test diff --git a/.github/workflows/release-package-splitter.yml b/.github/workflows/release-package-splitter.yml index fb5ee33b..b21a845a 100644 --- a/.github/workflows/release-package-splitter.yml +++ b/.github/workflows/release-package-splitter.yml @@ -83,14 +83,25 @@ jobs: FIRST=true # tj-actions outputs space-separated list for DIR in $CHANGED_DIRS; do + # Normalize potential trailing slash + DIR="${DIR%/}" + + # Collapse to the starter root (first two path segments), e.g. starters/landing-page + IFS='/' read -r SEG1 SEG2 _ <<< "$DIR" + if [[ -n "$SEG1" && -n "$SEG2" ]]; then + ROOT="$SEG1/$SEG2" + else + ROOT="$DIR" + fi + # Only process if it's a known starter - if [[ -n "${STARTER_MAP[$DIR]}" ]]; then + if [[ -n "${STARTER_MAP[$ROOT]}" ]]; then if [ "$FIRST" = true ]; then FIRST=false else - JSON+="," + JSON+="," fi - JSON+="{\"local_path\":\"$DIR\",\"split_repository\":\"${STARTER_MAP[$DIR]}\"}" + JSON+="{\"local_path\":\"$ROOT\",\"split_repository\":\"${STARTER_MAP[$ROOT]}\"}" fi done JSON+="]" diff --git a/modules/blox-tailwind/blox/collection/block.html b/modules/blox-tailwind/blox/collection/block.html index 24413a63..ac09a3fd 100644 --- a/modules/blox-tailwind/blox/collection/block.html +++ b/modules/blox-tailwind/blox/collection/block.html @@ -16,10 +16,13 @@ {{ end }} {{/* Query */}} -{{ $query := site.RegularPages }} +{{ $query := site.Pages }} {{ $archive_page := "" }} {{/* Filters */}} +{{ $kinds := $block.content.filters.kinds | default (slice "page") }} +{{ $query = where $query "Kind" "in" $kinds }} + {{ if $block.content.page_type }} {{ $query = where $query "Type" $block.content.page_type }} {{ $archive_page = site.GetPage "Section" $block.content.page_type }} @@ -31,6 +34,20 @@ {{ $main_folder := index $folders 0 }} {{ $archive_page = site.GetPage "Section" $main_folder }} {{ end }} +{{ if $block.content.filters.tags }} + {{ $tags := $block.content.filters.tags }} + {{ $selected := slice }} + {{ range $tags }} + {{ $tag_page := site.GetPage (printf "tags/%s" (urlize .)) }} + {{ if $tag_page }} + {{ $selected = $selected | union $tag_page.Pages }} + {{ end }} + {{ end }} + {{ if gt (len $selected) 0 }} + {{ $query = $query | intersect $selected }} + {{ $archive_page = site.GetPage (printf "tags/%s" (urlize (index $tags 0))) }} + {{ end }} +{{ end }} {{ if $block.content.filters.tag }} {{ $archive_page = site.GetPage (printf "tags/%s" (urlize $block.content.filters.tag)) }} {{ $query = $query | intersect $archive_page.Pages }} diff --git a/modules/blox-tailwind/i18n/en.yaml b/modules/blox-tailwind/i18n/en.yaml index 04379c6b..d55ef490 100644 --- a/modules/blox-tailwind/i18n/en.yaml +++ b/modules/blox-tailwind/i18n/en.yaml @@ -26,19 +26,52 @@ - id: related translation: Related -# Callouts +# Callouts - All Obsidian-compatible types - id: callout_note translation: Note +- id: callout_abstract + translation: Abstract + +- id: callout_summary + translation: Summary + +- id: callout_info + translation: Info + +- id: callout_todo + translation: Todo + - id: callout_tip translation: Tip -- id: callout_important - translation: Important +- id: callout_success + translation: Success + +- id: callout_question + translation: Question - id: callout_warning translation: Warning +- id: callout_failure + translation: Failure + +- id: callout_danger + translation: Danger + +- id: callout_bug + translation: Bug + +- id: callout_example + translation: Example + +- id: callout_quote + translation: Quote + +- id: callout_important + translation: Important + - id: callout_caution translation: Caution diff --git a/modules/blox-tailwind/i18n/es.yaml b/modules/blox-tailwind/i18n/es.yaml index 32d7d1f6..567c952d 100644 --- a/modules/blox-tailwind/i18n/es.yaml +++ b/modules/blox-tailwind/i18n/es.yaml @@ -26,19 +26,52 @@ - id: related translation: Relacionado -# Callouts +# Callouts - All Obsidian-compatible types - id: callout_note translation: Nota +- id: callout_abstract + translation: Resumen + +- id: callout_summary + translation: Resumen + +- id: callout_info + translation: Info + +- id: callout_todo + translation: Pendiente + - id: callout_tip translation: Consejo -- id: callout_important - translation: Importante +- id: callout_success + translation: Éxito + +- id: callout_question + translation: Pregunta - id: callout_warning translation: Advertencia +- id: callout_failure + translation: Fallo + +- id: callout_danger + translation: Peligro + +- id: callout_bug + translation: Error + +- id: callout_example + translation: Ejemplo + +- id: callout_quote + translation: Cita + +- id: callout_important + translation: Importante + - id: callout_caution translation: Precaución diff --git a/modules/blox-tailwind/i18n/fr.yaml b/modules/blox-tailwind/i18n/fr.yaml index 2845cf93..065b01b9 100644 --- a/modules/blox-tailwind/i18n/fr.yaml +++ b/modules/blox-tailwind/i18n/fr.yaml @@ -26,19 +26,52 @@ - id: related translation: Sur le même sujet -# Callouts +# Callouts - All Obsidian-compatible types - id: callout_note translation: Note +- id: callout_abstract + translation: Résumé + +- id: callout_summary + translation: Résumé + +- id: callout_info + translation: Info + +- id: callout_todo + translation: À faire + - id: callout_tip translation: Conseil -- id: callout_important - translation: Important +- id: callout_success + translation: Succès + +- id: callout_question + translation: Question - id: callout_warning translation: Attention +- id: callout_failure + translation: Échec + +- id: callout_danger + translation: Danger + +- id: callout_bug + translation: Bug + +- id: callout_example + translation: Exemple + +- id: callout_quote + translation: Citation + +- id: callout_important + translation: Important + - id: callout_caution translation: Prudence diff --git a/modules/blox-tailwind/layouts/_partials/functions/get-build-id.html b/modules/blox-tailwind/layouts/_partials/functions/get-build-id.html new file mode 100644 index 00000000..18a8cbb9 --- /dev/null +++ b/modules/blox-tailwind/layouts/_partials/functions/get-build-id.html @@ -0,0 +1,5 @@ +{{/* + Get Build ID - Returns a consistent build identifier for the current build cycle. + This is cached across the entire build to prevent log duplication during dev rebuilds. +*/}} +{{- printf "%d" now.Unix -}} diff --git a/modules/blox-tailwind/layouts/_partials/functions/get_icon.html b/modules/blox-tailwind/layouts/_partials/functions/get_icon.html index fa518144..eaea85e0 100644 --- a/modules/blox-tailwind/layouts/_partials/functions/get_icon.html +++ b/modules/blox-tailwind/layouts/_partials/functions/get_icon.html @@ -20,10 +20,33 @@ {{ with index (index site.Data.icons.hb "icons") $name -}} {{ $icon = . }} {{ else }} - {{ with resources.GetMatch (path.Join "media" "icons" $pack (printf "%s.svg" $name)) }} + {{- $prefix := printf "media/icons/%s/" $pack -}} + {{- $icon_path := printf "%s%s.svg" $prefix $name -}} + {{- if not (fileExists (printf "assets/%s" $icon_path)) -}} + {{ $pageRef := "unknown location" }} + {{ if .Page }} + {{ if .Page.File }} + {{ if .Page.File.Path }} + {{ $pageRef = .Page.File.Path }} + {{ else if .Page.RelPermalink }} + {{ $pageRef = .Page.RelPermalink }} + {{ end }} + {{ else if .Page.RelPermalink }} + {{ $pageRef = .Page.RelPermalink }} + {{ end }} + {{ end }} + {{ partial "functions/logger" (dict + "page" .Page + "level" "warn" + "id" (printf "missing-icon-%s-%s" $pack $name) + "message" (printf "The icon `%s` was not found in `assets/media/icons/%s/`. Referenced in: %s" $name $pack $pageRef) + ) + }} + {{- end -}} + {{- $icon := resources.Get $icon_path -}} + {{ if $icon }} {{ $icon = .Content }} - {{else}} - {{ partial "functions/logger" (dict "page" $.Page "level" "warn" "message" (printf "The icon `%s.svg` was not found in your `assets/media/icons/%s/` folder" $name $pack)) }} + {{ else }} {{ $icon = index (index site.Data.icons.brands "icons") "hugo" }} {{ end }} {{ end }} diff --git a/modules/blox-tailwind/layouts/_partials/functions/logger.html b/modules/blox-tailwind/layouts/_partials/functions/logger.html index 98c23ea8..bcb2582e 100644 --- a/modules/blox-tailwind/layouts/_partials/functions/logger.html +++ b/modules/blox-tailwind/layouts/_partials/functions/logger.html @@ -1,51 +1,51 @@ -{{/* Hugo Blox Logger: centralized logging helper - Usage: partial "functions/logger" (dict "page" . "level" "warn" "message" (printf "..." args...)) - - level: "warn" (default) or "error" - - page: optional; current page. Defaults to dot. Used to detect adapter pages - - adapter: optional bool to force adapter-safe mode (e.g., from _content.gotmpl) -*/}} -{{- $level := lower (.level | default "warn") -}} -{{- $msg := .message | default "" -}} -{{- $page := .page | default . -}} -{{- $forceAdapter := .adapter | default false -}} -{{- $isDev := or hugo.IsServer (eq hugo.Environment "development") -}} +{{/* + Hugo Blox Logger: A pragmatic, centralized logging helper for Hugo. -{{/* Detect adapter-generated pages via explicit flag or page param */}} -{{- $isAdapter := $forceAdapter -}} -{{- if not $isAdapter -}} - {{- with $page -}} - {{- with .Params -}} - {{- if or (index . "hb_adapter") (eq (printf "%T" .) "map[string]interface {}" | and (index . "hb_adapter")) -}} - {{- $isAdapter = true -}} - {{- end -}} + This partial is the single source of truth for all build-time logging. + Hugo's template logging is limited to WARN and ERROR. INFO is only shown in the Dev HUD/JSON, not the CLI. + + Usage: + {{ partial "functions/logger" (dict + "page" . + "level" "info" | "warn" | "error" (default: "info") + "message" "Your log message here." + "id" "a-unique-id" (optional, for suppressible warnings) + "source" (dict "type" "shortcode|partial|template" "name" "callout|sections" ) (optional) + ) }} +*/}} +{{- $level := lower (.level | default "info") -}} +{{- $message := .message | default "" -}} +{{- $id := .id | default "" -}} +{{- $source := .source | default dict -}} +{{- $page := .page | default . -}} +{{- $isDev := hugo.IsServer -}} + +{{/* Store log entry for future debug widget/JSON, regardless of environment. */}} +{{- with $page -}} + {{- with .Store -}} + {{- $buildId := partialCached "functions/get-build-id.html" "hbx-build-id" -}} + {{- $log_entry := dict "level" $level "message" $message "page" ($.RelPermalink | default "/") "timestamp" now.Unix "id" $id "source" $source "buildId" $buildId -}} + {{- $current_logs := .Get "hbx_logs" | default slice -}} + {{- $currentBuildId := .Get "hbx_build_id" | default "" -}} + {{/* Clear logs if this is a new build cycle */}} + {{- if ne $currentBuildId $buildId -}} + {{- .Set "hbx_build_id" $buildId -}} + {{- $current_logs = slice -}} {{- end -}} + {{- .Set "hbx_logs" ($current_logs | append $log_entry) -}} {{- end -}} {{- end -}} -{{/* Store log entry for future debug widget */}} -{{- with $page -}} - {{- $log_entry := dict "level" $level "message" $msg "page" ($.RelPermalink | default "/") "timestamp" now.Unix -}} - {{- $current_logs := .Store.Get "hbx_logs" | default slice -}} - {{- .Store.Set "hbx_logs" ($current_logs | append $log_entry) -}} -{{- end -}} - -{{/* Multi-tier logging output */}} -{{- if $isDev -}} - {{/* Console logging for immediate dev feedback */}} - -{{- end -}} - +{{/* Emit to CLI using fmt with proper severity. Do not print INFO to CLI. */}} {{- if eq $level "error" -}} - {{- if not $isAdapter -}} - {{- errorf "%s" $msg -}} + {{- fmt.Errorf "HBX ERROR: %s" $message -}} +{{- else if eq $level "warn" -}} + {{- if $id -}} + {{- fmt.Warnidf $id "HBX WARN: %s" $message -}} {{- else -}} - {{- if $isDev -}}{{- end -}} + {{- fmt.Warnf "HBX WARN: %s" $message -}} {{- end -}} {{- else -}} - {{- if not $isAdapter -}} - {{- warnf "%s" $msg -}} - {{- else -}} - {{- if $isDev -}}{{- end -}} - {{- end -}} + {{/* info: no CLI output; visible via Dev HUD/JSON only */}} {{- end -}} {{- "" -}} diff --git a/modules/blox-tailwind/layouts/_partials/functions/render_callout.html b/modules/blox-tailwind/layouts/_partials/functions/render_callout.html new file mode 100644 index 00000000..ad1ccbbc --- /dev/null +++ b/modules/blox-tailwind/layouts/_partials/functions/render_callout.html @@ -0,0 +1,155 @@ +{{/* + Hugo Blox Builder Shared Callout Renderer + + Renders callouts with consistent styling for both shortcodes and render hooks. + + Parameters: + - type: The callout type (note, tip, important, warning, caution, or custom icon name) + - content: The callout content (HTML) + - title: Optional title for the callout + - source: "shortcode" or "renderhook" for context +*/}} + +{{ $type := (lower .type) | default "note" }} +{{ $content := .content }} +{{ $title := .title }} +{{ if or (not $title) (eq $title "") }} + {{/* Try i18n translation with "callout_" prefix, fall back to title case */}} + {{ $i18n_key := printf "callout_%s" $type }} + {{ $title = or (i18n $i18n_key) (title $type) }} +{{ end }} +{{ $source := .source | default "shortcode" }} + +{{/* Define icon and styling mappings for all Obsidian callout types */}} +{{ $alertConfigs := dict + "note" (dict + "icon" "pencil" + "class" "bg-blue-100 dark:bg-blue-900" + "textClass" "text-blue-600 dark:text-blue-300" + "borderClass" "border-blue-500" + ) + "abstract" (dict + "icon" "clipboard-document-list" + "class" "bg-cyan-100 dark:bg-cyan-900" + "textClass" "text-cyan-600 dark:text-cyan-300" + "borderClass" "border-cyan-500" + ) + "summary" (dict + "icon" "clipboard-document-list" + "class" "bg-cyan-100 dark:bg-cyan-900" + "textClass" "text-cyan-600 dark:text-cyan-300" + "borderClass" "border-cyan-500" + ) + "info" (dict + "icon" "information-circle" + "class" "bg-blue-100 dark:bg-blue-900" + "textClass" "text-blue-600 dark:text-blue-300" + "borderClass" "border-blue-500" + ) + "todo" (dict + "icon" "check-circle" + "class" "bg-blue-100 dark:bg-blue-900" + "textClass" "text-blue-600 dark:text-blue-300" + "borderClass" "border-blue-500" + ) + "tip" (dict + "icon" "light-bulb" + "class" "bg-emerald-100 dark:bg-emerald-900" + "textClass" "text-emerald-600 dark:text-emerald-300" + "borderClass" "border-emerald-500" + ) + "success" (dict + "icon" "check-circle" + "class" "bg-green-100 dark:bg-green-900" + "textClass" "text-green-600 dark:text-green-300" + "borderClass" "border-green-500" + ) + "question" (dict + "icon" "question-mark-circle" + "class" "bg-yellow-100 dark:bg-yellow-900" + "textClass" "text-yellow-700 dark:text-yellow-300" + "borderClass" "border-yellow-500" + ) + "warning" (dict + "icon" "exclamation-triangle" + "class" "bg-orange-100 dark:bg-orange-900" + "textClass" "text-orange-600 dark:text-orange-300" + "borderClass" "border-orange-500" + ) + "failure" (dict + "icon" "x-circle" + "class" "bg-red-100 dark:bg-red-900" + "textClass" "text-red-600 dark:text-red-300" + "borderClass" "border-red-500" + ) + "danger" (dict + "icon" "exclamation-triangle" + "class" "bg-red-100 dark:bg-red-900" + "textClass" "text-red-600 dark:text-red-300" + "borderClass" "border-red-500" + ) + "bug" (dict + "icon" "bug-ant" + "class" "bg-red-100 dark:bg-red-900" + "textClass" "text-red-600 dark:text-red-300" + "borderClass" "border-red-500" + ) + "example" (dict + "icon" "beaker" + "class" "bg-purple-100 dark:bg-purple-900" + "textClass" "text-purple-600 dark:text-purple-300" + "borderClass" "border-purple-500" + ) + "quote" (dict + "icon" "chat-bubble-left-right" + "class" "bg-gray-100 dark:bg-gray-800" + "textClass" "text-gray-600 dark:text-gray-300" + "borderClass" "border-gray-500" + ) + "important" (dict + "icon" "exclamation-circle" + "class" "bg-purple-100 dark:bg-purple-900" + "textClass" "text-purple-600 dark:text-purple-300" + "borderClass" "border-purple-500" + ) + "caution" (dict + "icon" "exclamation-triangle" + "class" "bg-red-100 dark:bg-red-900" + "textClass" "text-red-600 dark:text-red-300" + "borderClass" "border-red-500" + ) +}} + +{{/* Get configuration for this callout type, or use fallback */}} +{{ $config := index $alertConfigs $type }} +{{ $icon := $type }} +{{ $class := "bg-blue-100 dark:bg-blue-900" }} +{{ $textClass := "text-blue-600 dark:text-blue-300" }} +{{ $borderClass := "border-blue-500" }} + +{{ if $config }} + {{ $icon = $config.icon }} + {{ $class = $config.class }} + {{ $textClass = $config.textClass }} + {{ $borderClass = $config.borderClass }} +{{ end }} + +