快轉到主要內容
  1. 全部文章/

Hugo Blowfish 主題|切換文章列表樣式按鈕

·4248 字·9 分鐘
目錄
Hugo Blowfish 主題客製化 - 本文屬於一個選集。
§ 5: 本文

前言
#

從我創建個人部落格「YoZ Blog 」以來,我在主頁與文章列表頁面都是使用「卡片列表」的樣式呈現文章,我認為較美觀,但後來發現文章越寫越多,這樣的樣式比起簡單的「列表」,似乎會妨礙到快速地找尋文章,且許多寫部落格的人也都使用單純的列表樣式,便產生了增加一個功能,透過按鈕切換文章列表樣式的功能,於是我透過 Cursor 稍微更改(vibecode)了 Blowfish 主題(2.93 版本)。

成品可以直接到 YoZ Blog 的主頁觀看。

下面直接說明這個過程。

創建切換按鍵 Javascript
#

首先先建立/assets/js/switch-article-view.js

(() => {
  const activeClasses = ["bg-primary-500", "border-primary-500", "text-white"];
  const inactiveClasses = [
    "bg-transparent",
    "border-neutral-300",
    "text-neutral-700",
    "dark:text-neutral-200",
    "dark:border-neutral-600",
  ];

  const setupToggle = (config) => {
    const container = document.getElementById(config.toggleId);
    const card = document.getElementById(config.cardId);
    const list = document.getElementById(config.listId);
    if (!container || !card || !list) return;

    const buttons = Array.from(container.querySelectorAll("[data-view]"));
    if (!buttons.length) return;

    const setView = (view) => {
      card.classList.toggle("hidden", view !== "card");
      list.classList.toggle("hidden", view !== "list");

      buttons.forEach((btn) => {
        const isActive = btn.dataset.view === view;
        btn.setAttribute("aria-pressed", isActive ? "true" : "false");
        btn.classList.remove(...(isActive ? inactiveClasses : activeClasses));
        btn.classList.add(...(isActive ? activeClasses : inactiveClasses));
      });
    };

    buttons.forEach((btn) => {
      btn.addEventListener("click", () => setView(btn.dataset.view || "card"));
    });

    setView(container.dataset.defaultView || "card");
  };

  [
    { toggleId: "recent-articles-toggle", cardId: "recent-articles-card", listId: "recent-articles-list" },
    { toggleId: "posts-view-toggle", cardId: "posts-card-view", listId: "posts-list-view" },
    { toggleId: "term-view-toggle", cardId: "term-card-view", listId: "term-list-view" },
  ].forEach(setupToggle);
})();

創建列表模式模板
#

列表模板的樣式相當簡單,只顯示「文章日期」與「文章標題」,例如:2026-03-07 Hugo Blowfish 主題|切換文章列表樣式按鈕

創建/layouts/partials/recent-articles/title-list.html

{{ $recentArticles := 5 }}
{{ if index .Site.Params.homepage "showRecentItems" }}
  {{ $recentArticles = .Site.Params.homepage.showRecentItems }}
{{ end }}

<ul class="divide-y divide-neutral-200 dark:divide-neutral-800">
  {{ range first $recentArticles (.Paginate (where .Site.RegularPages "Type" "in" .Site.Params.mainSections)).Pages }}
    <li class="py-3">
      <div class="flex items-center">
        <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
          {{ .Date.Format "2006-01-02" }}
        </span>
        <a
          href="{{ .RelPermalink }}"
          class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
          {{ .Title | emojify }}
        </a>
      </div>
    </li>
  {{ end }}
</ul>

主頁最新文章
#

接著要套用到主頁上的最新文章段落。

先複製/themes/blowfish/layouts/partials/recent-articles/路徑下的main.html/layouts/partials/recent-articles

將原本的程式碼:

{{ $recentArticles := 5 }}
{{ $showMoreLinkDest := "/posts/" }}
{{ if .Site.Params.homepage.showRecent | default false }}
  {{ if index .Site.Params.homepage "showRecentItems" }}
    {{ $recentArticles = .Site.Params.homepage.showRecentItems }}
  {{ end }}
  <h2 class="mt-8 text-2xl font-extrabold mb-10">{{ i18n "shortcode.recent_articles" | emojify }}</h2>

  {{ if and .Site.Params.homepage.cardView (not .Site.Params.homepage.cardViewScreenWidth) | default false }}
    {{ partial "recent-articles/cardview.html" . }}
  {{ else if and .Site.Params.homepage.cardView .Site.Params.homepage.cardViewScreenWidth | default false }}
    {{ partial "recent-articles/cardview-fullwidth.html" . }}
  {{ else }}
    {{ partial "recent-articles/list.html" . }}
  {{ end }}

  {{ if .Site.Params.homepage.showMoreLink | default false }}
    {{ if index .Site.Params.homepage "showRecentItems" }}
      {{ $showMoreLinkDest = .Site.Params.homepage.showMoreLinkDest }}
    {{ end }}
    <div class="mt-10 flex justify-center">
      <a href="{{ $showMoreLinkDest | relLangURL }}">
        <button
          class="bg-transparent hover:text-primary-500 prose dark:prose-invert font-semibold py-2 px-4 border border-primary-500 hover:border-transparent rounded">
          {{ i18n "recent.show_more" | markdownify }}
        </button>
      </a>
    </div>
  {{ end }}
{{ end }}

更改為:

{{ $recentArticles := 5 }}
{{ $showMoreLinkDest := "/posts/" }}
{{ $showRecent := .Site.Params.homepage.showRecent | default false }}
{{ $isCardDefault := .Site.Params.homepage.cardView | default false }}
{{ $defaultView := cond $isCardDefault "card" "list" }}

{{ if $showRecent }}
  {{ if index .Site.Params.homepage "showRecentItems" }}
    {{ $recentArticles = .Site.Params.homepage.showRecentItems }}
  {{ end }}

  <div class="mt-8 flex flex-wrap items-center justify-between gap-3 mb-6">
    <h2 class="m-0 text-2xl font-extrabold leading-tight">
      {{ i18n "shortcode.recent_articles" | emojify }}
    </h2>
    <div
      id="recent-articles-toggle"
      class="flex items-center"
      style="gap: 0.5rem;"
      data-default-view="{{ $defaultView }}">
      {{ $btnBase := "px-3 py-1 rounded-md border text-sm font-medium transition-colors" }}
      <button
        type="button"
        class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "card" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
        data-view="card"
        aria-pressed="{{ if eq $defaultView "card" }}true{{ else }}false{{ end }}">
        卡片
      </button>
      <button
        type="button"
        class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "list" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
        data-view="list"
        aria-pressed="{{ if eq $defaultView "list" }}true{{ else }}false{{ end }}">
        列表
      </button>
    </div>
  </div>

  <div id="recent-articles-card" class="{{ if ne $defaultView "card" }}hidden{{ end }}">
    {{ if and .Site.Params.homepage.cardView (not .Site.Params.homepage.cardViewScreenWidth) | default false }}
      {{ partial "recent-articles/cardview.html" . }}
    {{ else if and .Site.Params.homepage.cardView .Site.Params.homepage.cardViewScreenWidth | default false }}
      {{ partial "recent-articles/cardview-fullwidth.html" . }}
    {{ else }}
      {{ partial "recent-articles/cardview.html" . }}
    {{ end }}
  </div>

  <div id="recent-articles-list" class="{{ if ne $defaultView "list" }}hidden{{ end }}">
    {{ partial "recent-articles/title-list.html" . }}
  </div>

  {{ if .Site.Params.homepage.showMoreLink | default false }}
    {{ if index .Site.Params.homepage "showRecentItems" }}
      {{ $showMoreLinkDest = .Site.Params.homepage.showMoreLinkDest }}
    {{ end }}
    <div class="mt-10 flex justify-center">
      <a href="{{ $showMoreLinkDest | relLangURL }}">
        <button
          class="bg-transparent hover:text-primary-500 prose dark:prose-invert font-semibold py-2 px-4 border border-primary-500 hover:border-transparent rounded">
          {{ i18n "recent.show_more" | markdownify }}
        </button>
      </a>
    </div>
  {{ end }}
  {{ $recentToggle := resources.Get "js/switch-article-view.js" }}
  {{ $recentToggle = $recentToggle | resources.Minify | resources.Fingerprint (.Site.Params.fingerprintAlgorithm | default "sha512") }}
  <script
    src="{{ $recentToggle.RelPermalink }}"
    integrity="{{ $recentToggle.Data.Integrity }}"
    defer></script>
{{ end }}

完成!

全部文章
#

接著要套用到全部文章 (/posts)的段落。

/themes/blowfish/layouts/_default路徑下的list.html複製到 /layouts/_default

將原本的程式碼:

{{ define "main" }}
  {{ .Scratch.Set "scope" "list" }}
  {{ $enableToc := .Params.showTableOfContents | default (site.Params.list.showTableOfContents | default false) }}
  {{ $showToc := and $enableToc (in .TableOfContents "<ul") }}

  {{/* Hero */}}
  {{ if site.Params.list.showHero | default false }}
    {{ $heroStyle := print "hero/" site.Params.list.heroStyle ".html" }}
    {{ if templates.Exists ( printf "partials/%s" $heroStyle ) }}
      {{ partial $heroStyle . }}
    {{ else }}
      {{ partial "hero/basic.html" . }}
    {{ end }}
  {{ end }}

  {{/* Header */}}
  <header>
    {{ if .Params.showBreadcrumbs | default (site.Params.list.showBreadcrumbs | default false) }}
      {{ partial "breadcrumbs.html" . }}
    {{ end }}
    <h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">{{ .Title }}</h1>
    <div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden">
      {{ partial "article-meta/list.html" (dict "context" . "scope" "single") }}
    </div>
    {{ $translations := .AllTranslations }}
    {{ with .File }}
      {{ $path := .Path }}
      {{ range $translations }}
        {{ $lang := print "."  .Lang  ".md" }}
        {{ $path = replace $path $lang ".md" }}
      {{ end }}
      {{ $jsPage := resources.Get "js/page.js" }}
      {{ $jsPage = $jsPage | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
      <script
        type="text/javascript"
        src="{{ $jsPage.RelPermalink }}"
        integrity="{{ $jsPage.Data.Integrity }}"
        data-oid="views_{{ $path }}"
        data-oid-likes="likes_{{ $path }}"></script>
    {{ end }}
  </header>

  {{/* Description (markdown content) */}}
  {{ $tocMargin := cond $showToc "mt-12" "mt-0" }}
  {{ $topClass := cond (hasPrefix site.Params.header.layout "fixed") "lg:top-[140px]" "lg:top-10" }}
  <section class="{{ $tocMargin }} prose flex max-w-full flex-col dark:prose-invert lg:flex-row">
    {{ if $showToc }}
      <div class="order-first px-0 lg:order-last lg:max-w-xs lg:ps-8">
        <div class="toc ps-5 lg:sticky {{ $topClass }}">
          {{ partial "toc.html" . }}
        </div>
      </div>
    {{ end }}
    <div class="min-w-0 min-h-0 max-w-prose">
      {{ .Content }}
    </div>
  </section>

  {{/* Article Grid */}}
  {{ if gt .Pages 0 }}
    {{ $cardView := .Params.cardView | default (site.Params.list.cardView | default false) }}
    {{ $cardViewScreenWidth := .Params.cardViewScreenWidth | default (site.Params.list.cardViewScreenWidth | default false) }}
    {{ $groupByYear := .Params.groupByYear | default (site.Params.list.groupByYear | default false) }}
    {{ $orderByWeight := .Params.orderByWeight | default (site.Params.list.orderByWeight | default false) }}
    {{ $groupByYear := and (not $orderByWeight) $groupByYear }}

    {{ if not $cardView }}
      <section class="space-y-10 w-full">
        {{ if not $orderByWeight }}
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            {{ if $groupByYear }}
              <h2 class="mt-12 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
                {{ .Key }}
              </h2>
            {{ end }}
            {{ range .Pages }}
              {{ partial "article-link/simple.html" . }}
            {{ end }}
          {{ end }}
        {{ else }}
          {{ range (.Paginate (.Pages.ByWeight)).Pages }}
            {{ partial "article-link/simple.html" . }}
          {{ end }}
        {{ end }}
      </section>
    {{/* else: is cardView */}}
    {{ else }}
      {{ if $groupByYear }}
        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          {{ if $cardViewScreenWidth }}
            <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
              <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
                {{ .Key }}
              </h2>
              <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              </section>
            </div>
          {{ else }}
            <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
              {{ .Key }}
            </h2>
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            </section>
          {{ end }}
        {{ end }}

      {{/* else: not groupByYear */}}
      {{ else }}
        {{ if $cardViewScreenWidth }}
          <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
              {{ if not $orderByWeight }}
                {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
                  {{ range .Pages }}
                    {{ partial "article-link/card.html" . }}
                  {{ end }}
                {{ end }}
              {{ else }}
                {{ range (.Paginate (.Pages.ByWeight)).Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              {{ end }}
            </section>
          </div>
        {{ else }}
          <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
            {{ if not $orderByWeight }}
              {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              {{ end }}
            {{ else }}
              {{ range (.Paginate (.Pages.ByWeight)).Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            {{ end }}
          </section>
        {{ end }}{{/* End of cardViewScreenWidth */}}
      {{ end }}{{/* End of groupByYear */}}
    {{ end }}{{/* End of cardView */}}
  {{/* else: .Pages not greater to zero */}}
  {{ else }}
    <section class="mt-10 prose dark:prose-invert">
      <p class="py-8 border-t">
        <em>{{ i18n "list.no_articles" | emojify }}</em>
      </p>
    </section>
  {{ end }}
  {{ partial "pagination.html" . }}
{{ end }}

更改為:

{{ define "main" }}
  {{ .Scratch.Set "scope" "list" }}
  {{ $enableToc := .Params.showTableOfContents | default (site.Params.list.showTableOfContents | default false) }}
  {{ $showToc := and $enableToc (in .TableOfContents "<ul") }}

  {{/* Hero */}}
  {{ if site.Params.list.showHero | default false }}
    {{ $heroStyle := print "hero/" site.Params.list.heroStyle ".html" }}
    {{ if templates.Exists ( printf "partials/%s" $heroStyle ) }}
      {{ partial $heroStyle . }}
    {{ else }}
      {{ partial "hero/basic.html" . }}
    {{ end }}
  {{ end }}

  {{/* Header */}}
  <header>
    {{ if .Params.showBreadcrumbs | default (site.Params.list.showBreadcrumbs | default false) }}
      {{ partial "breadcrumbs.html" . }}
    {{ end }}
    <h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">{{ .Title }}</h1>
    <div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden">
      {{ partial "article-meta/list.html" (dict "context" . "scope" "single") }}
    </div>
    {{ $translations := .AllTranslations }}
    {{ with .File }}
      {{ $path := .Path }}
      {{ range $translations }}
        {{ $lang := print "."  .Lang  ".md" }}
        {{ $path = replace $path $lang ".md" }}
      {{ end }}
      {{ $jsPage := resources.Get "js/page.js" }}
      {{ $jsPage = $jsPage | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
      <script
        type="text/javascript"
        src="{{ $jsPage.RelPermalink }}"
        integrity="{{ $jsPage.Data.Integrity }}"
        data-oid="views_{{ $path }}"
        data-oid-likes="likes_{{ $path }}"></script>
    {{ end }}
  </header>

  {{/* Description (markdown content) */}}
  {{ $tocMargin := cond $showToc "mt-12" "mt-0" }}
  {{ $topClass := cond (hasPrefix site.Params.header.layout "fixed") "lg:top-[140px]" "lg:top-10" }}
  <section class="{{ $tocMargin }} prose flex max-w-full flex-col dark:prose-invert lg:flex-row">
    {{ if $showToc }}
      <div class="order-first px-0 lg:order-last lg:max-w-xs lg:ps-8">
        <div class="toc ps-5 lg:sticky {{ $topClass }}">
          {{ partial "toc.html" . }}
        </div>
      </div>
    {{ end }}
    <div class="min-w-0 min-h-0 max-w-prose">
      {{ .Content }}
    </div>
  </section>

  {{/* Article Grid + Toggle */}}
  {{ if gt .Pages 0 }}
    {{ $cardView := .Params.cardView | default (site.Params.list.cardView | default false) }}
    {{ $cardViewScreenWidth := .Params.cardViewScreenWidth | default (site.Params.list.cardViewScreenWidth | default false) }}
    {{ $groupByYear := .Params.groupByYear | default (site.Params.list.groupByYear | default false) }}
    {{ $orderByWeight := .Params.orderByWeight | default (site.Params.list.orderByWeight | default false) }}
    {{ $groupByYear := and (not $orderByWeight) $groupByYear }}
    {{ $defaultView := cond $cardView "card" "list" }}

    <div class="mt-8 mb-2 flex justify-end">
      <div
        id="posts-view-toggle"
        class="flex items-center"
        style="gap: 0.5rem;"
        data-default-view="{{ $defaultView }}">
        {{ $btnBase := "px-3 py-1 rounded-md border text-sm font-medium transition-colors" }}
        <button
          type="button"
          class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "card" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
          data-view="card"
          aria-pressed="{{ if eq $defaultView "card" }}true{{ else }}false{{ end }}">
          卡片
        </button>
        <button
          type="button"
          class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "list" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
          data-view="list"
          aria-pressed="{{ if eq $defaultView "list" }}true{{ else }}false{{ end }}">
          列表
        </button>
      </div>
    </div>

    <div id="posts-card-view" class="{{ if ne $defaultView "card" }}hidden{{ end }}">
      {{ if $groupByYear }}
        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          {{ if $cardViewScreenWidth }}
            <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
              <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
                {{ .Key }}
              </h2>
              <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              </section>
            </div>
          {{ else }}
            <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
              {{ .Key }}
            </h2>
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            </section>
          {{ end }}
        {{ end }}
      {{ else }}
        {{ if $cardViewScreenWidth }}
          <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
              {{ if not $orderByWeight }}
                {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
                  {{ range .Pages }}
                    {{ partial "article-link/card.html" . }}
                  {{ end }}
                {{ end }}
              {{ else }}
                {{ range (.Paginate (.Pages.ByWeight)).Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              {{ end }}
            </section>
          </div>
        {{ else }}
          <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
            {{ if not $orderByWeight }}
              {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              {{ end }}
            {{ else }}
              {{ range (.Paginate (.Pages.ByWeight)).Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            {{ end }}
          </section>
        {{ end }}{{/* End of cardViewScreenWidth */}}
      {{ end }}{{/* End of groupByYear */}}
    </div>

    <div id="posts-list-view" class="{{ if ne $defaultView "list" }}hidden{{ end }}">
      {{ if $groupByYear }}
        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
            {{ .Key }}
          </h2>
          <ul class="divide-y divide-neutral-200 dark:divide-neutral-800">
            {{ range .Pages }}
              <li class="py-2">
                <div class="flex items-center">
                  <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
                    {{ .Date.Format "2006-01-02" }}
                  </span>
                  <a
                    href="{{ .RelPermalink }}"
                    class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
                    {{ .Title | emojify }}
                  </a>
                </div>
              </li>
            {{ end }}
          </ul>
        {{ end }}
      {{ else }}
        <ul class="divide-y divide-neutral-200 dark:divide-neutral-800">
          {{ if not $orderByWeight }}
            {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
              {{ range .Pages }}
                <li class="py-2">
                  <div class="flex items-center">
                    <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
                      {{ .Date.Format "2006-01-02" }}
                    </span>
                    <a
                      href="{{ .RelPermalink }}"
                      class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
                      {{ .Title | emojify }}
                    </a>
                  </div>
                </li>
              {{ end }}
            {{ end }}
          {{ else }}
            {{ range (.Paginate (.Pages.ByWeight)).Pages }}
              <li class="py-2">
                <div class="flex items-center">
                  <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
                    {{ .Date.Format "2006-01-02" }}
                  </span>
                  <a
                    href="{{ .RelPermalink }}"
                    class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
                    {{ .Title | emojify }}
                  </a>
                </div>
              </li>
            {{ end }}
          {{ end }}
        </ul>
      {{ end }}
    </div>
  {{/* else: .Pages not greater to zero */}}
  {{ else }}
    <section class="mt-10 prose dark:prose-invert">
      <p class="py-8 border-t">
        <em>{{ i18n "list.no_articles" | emojify }}</em>
      </p>
    </section>
  {{ end }}
  {{ partial "pagination.html" . }}

  {{ $switchView := resources.Get "js/switch-article-view.js" }}
  {{ $switchView = $switchView | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
  <script
    src="{{ $switchView.RelPermalink }}"
    integrity="{{ $switchView.Data.Integrity }}"
    defer></script>
{{ end }}

完成!

Taxonomy
#

接著要套用到自訂的 Taxonomy 頁面,像是各個分類 標籤

/themes/blowfish/layouts/_default路徑下的term.html複製到/layouts/_default/term.html

將原本的程式碼:

{{ define "main" }}
  {{ .Scratch.Set "scope" "term" }}
  {{ $showHero := .Params.showHero | default site.Params.term.showHero | default false }}
  {{ if $showHero }}
    {{ $heroStyle := print "hero/" site.Params.term.heroStyle ".html" }}
    {{ if templates.Exists ( printf "partials/%s" $heroStyle ) }}
      {{ partial $heroStyle . }}
    {{ else }}
      {{ partial "hero/basic.html" . }}
    {{ end }}
  {{- end -}}


  <header class="mt-5">
    {{ if .Params.showBreadcrumbs | default (site.Params.term.showBreadcrumbs | default false) }}
      {{ partial "breadcrumbs.html" . }}
    {{ end }}
    <h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">{{ .Title }}</h1>
    <div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden">
      {{ partial "article-meta/term.html" (dict "context" . "scope" "single") }}
    </div>
  </header>

  <section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row">
    {{ if .Content }}
      <div class="min-w-0 min-h-0 max-w-prose">
        {{ .Content }}
      </div>
      {{ $jsPage := resources.Get "js/page.js" }}
      {{ $jsPage = $jsPage | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
      <script
        type="text/javascript"
        src="{{ $jsPage.RelPermalink }}"
        integrity="{{ $jsPage.Data.Integrity }}"
        data-oid="views_term_{{ .Data.Term }}"
        data-oid-likes="likes_term_{{ .Data.Term }}"></script>
    {{ end }}
  </section>

  {{ if gt .Pages 0 }}
    {{ $cardView := .Params.cardView | default (site.Params.term.cardView | default false) }}
    {{ $cardViewScreenWidth := site.Params.term.cardViewScreenWidth | default false }}
    {{ $groupByYear := .Params.groupByYear | default (site.Params.term.groupByYear | default false) }}

    {{ if not $cardView }}

      <section class="space-y-10 w-full">
        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          {{ if $groupByYear }}
            <h2 class="mt-12 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
              {{ .Key }}
            </h2>
          {{ end }}
          {{ range .Pages }}
            {{ partial "article-link/simple.html" . }}
          {{ end }}
        {{ end }}
      </section>
    {{ else if and $cardView (not $cardViewScreenWidth) }}

      {{ if $groupByYear }}

        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
            {{ .Key }}
          </h2>
          <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
            {{ range .Pages }}
              {{ partial "article-link/card.html" . }}
            {{ end }}
          </section>
        {{ end }}

      {{ else }}

        <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            {{ range .Pages }}
              {{ partial "article-link/card.html" . }}
            {{ end }}
          {{ end }}
        </section>
      {{ end }}

    {{ else if and $cardView $cardViewScreenWidth }}

      {{ if $groupByYear }}

        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
            <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
              {{ .Key }}
            </h2>
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            </section>
          </div>
        {{ end }}

      {{ else }}

        <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
          <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
            {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            {{ end }}
          </section>
        </div>
      {{ end }}

    {{ end }}

  {{ else }}
    <section class="mt-10 prose dark:prose-invert">
      <p class="py-8 border-t">
        <em>{{ i18n "term.no_articles" | emojify }}</em>
      </p>
    </section>
  {{ end }}

  {{ partial "pagination.html" . }}
{{ end }}

更改為:

{{ define "main" }}
  {{ .Scratch.Set "scope" "term" }}
  {{ $showHero := .Params.showHero | default site.Params.term.showHero | default false }}
  {{ if $showHero }}
    {{ $heroStyle := print "hero/" site.Params.term.heroStyle ".html" }}
    {{ if templates.Exists ( printf "partials/%s" $heroStyle ) }}
      {{ partial $heroStyle . }}
    {{ else }}
      {{ partial "hero/basic.html" . }}
    {{ end }}
  {{- end -}}

  <header class="mt-5">
    {{ if .Params.showBreadcrumbs | default (site.Params.term.showBreadcrumbs | default false) }}
      {{ partial "breadcrumbs.html" . }}
    {{ end }}
    <h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">{{ .Title }}</h1>
    <div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden">
      {{ partial "article-meta/term.html" (dict "context" . "scope" "single") }}
    </div>
  </header>

  <section class="flex flex-col max-w-full mt-0 mb-5 prose dark:prose-invert lg:flex-row">
    {{ if .Content }}
      <div class="min-w-0 min-h-0 max-w-prose">
        {{ .Content }}
      </div>
      {{ $jsPage := resources.Get "js/page.js" }}
      {{ $jsPage = $jsPage | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
      <script
        type="text/javascript"
        src="{{ $jsPage.RelPermalink }}"
        integrity="{{ $jsPage.Data.Integrity }}"
        data-oid="views_term_{{ .Data.Term }}"
        data-oid-likes="likes_term_{{ .Data.Term }}"></script>
    {{ end }}
  </section>

  {{ if gt .Pages 0 }}
    {{ $cardView := .Params.cardView | default (site.Params.term.cardView | default false) }}
    {{ $cardViewScreenWidth := site.Params.term.cardViewScreenWidth | default false }}
    {{ $groupByYear := .Params.groupByYear | default (site.Params.term.groupByYear | default false) }}
    {{ $defaultView := cond $cardView "card" "list" }}

    <div class="mt-6 mb-2 flex justify-end">
      <div
        id="term-view-toggle"
        class="flex items-center"
        style="gap: 0.5rem;"
        data-default-view="{{ $defaultView }}">
        {{ $btnBase := "px-3 py-1 rounded-md border text-sm font-medium transition-colors" }}
        <button
          type="button"
          class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "card" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
          data-view="card"
          aria-pressed="{{ if eq $defaultView "card" }}true{{ else }}false{{ end }}">
          卡片
        </button>
        <button
          type="button"
          class="{{ $btnBase }} recent-toggle-button {{ if eq $defaultView "list" }}bg-primary-500 border-primary-500 text-white{{ else }}bg-transparent border-neutral-300 text-neutral-700 dark:text-neutral-200 dark:border-neutral-600{{ end }}"
          data-view="list"
          aria-pressed="{{ if eq $defaultView "list" }}true{{ else }}false{{ end }}">
          列表
        </button>
      </div>
    </div>

    <div id="term-card-view" class="{{ if ne $defaultView "card" }}hidden{{ end }}">
      {{ if not $cardView }}
        <section class="space-y-10 w-full">
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            {{ if $groupByYear }}
              <h2 class="mt-12 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
                {{ .Key }}
              </h2>
            {{ end }}
            {{ range .Pages }}
              {{ partial "article-link/simple.html" . }}
            {{ end }}
          {{ end }}
        </section>
      {{ else if and $cardView (not $cardViewScreenWidth) }}
        {{ if $groupByYear }}
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
              {{ .Key }}
            </h2>
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            </section>
          {{ end }}
        {{ else }}
          <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3">
            {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
              {{ range .Pages }}
                {{ partial "article-link/card.html" . }}
              {{ end }}
            {{ end }}
          </section>
        {{ end }}
      {{ else if and $cardView $cardViewScreenWidth }}
        {{ if $groupByYear }}
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
              <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
                {{ .Key }}
              </h2>
              <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              </section>
            </div>
          {{ end }}
        {{ else }}
          <div class="relative w-screen max-w-[1600px] px-[30px] start-[calc(max(-50vw,-800px)+50%)]">
            <section class="w-full grid gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
              {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
                {{ range .Pages }}
                  {{ partial "article-link/card.html" . }}
                {{ end }}
              {{ end }}
            </section>
          </div>
        {{ end }}
      {{ end }}
    </div>

    <div id="term-list-view" class="{{ if ne $defaultView "list" }}hidden{{ end }}">
      {{ if $groupByYear }}
        {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
          <h2 class="mt-12 mb-3 text-2xl font-bold text-neutral-700 first:mt-8 dark:text-neutral-300">
            {{ .Key }}
          </h2>
          <ul class="divide-y divide-neutral-200 dark:divide-neutral-800">
            {{ range .Pages }}
              <li class="py-2">
                <div class="flex items-center">
                  <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
                    {{ .Date.Format "2006-01-02" }}
                  </span>
                  <a
                    href="{{ .RelPermalink }}"
                    class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
                    {{ .Title | emojify }}
                  </a>
                </div>
              </li>
            {{ end }}
          </ul>
        {{ end }}
      {{ else }}
        <ul class="divide-y divide-neutral-200 dark:divide-neutral-800">
          {{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }}
            {{ range .Pages }}
              <li class="py-2">
                <div class="flex items-center">
                  <span class="text-sm text-neutral-500 dark:text-neutral-400 whitespace-nowrap mr-3">
                    {{ .Date.Format "2006-01-02" }}
                  </span>
                  <a
                    href="{{ .RelPermalink }}"
                    class="font-semibold text-neutral-800 dark:text-neutral-100 hover:underline hover:underline-offset-2">
                    {{ .Title | emojify }}
                  </a>
                </div>
              </li>
            {{ end }}
          {{ end }}
        </ul>
      {{ end }}
    </div>
  {{ else }}
    <section class="mt-10 prose dark:prose-invert">
      <p class="py-8 border-t">
        <em>{{ i18n "term.no_articles" | emojify }}</em>
      </p>
    </section>
  {{ end }}

  {{ partial "pagination.html" . }}

  {{ $switchView := resources.Get "js/switch-article-view.js" }}
  {{ $switchView = $switchView | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
  <script
    src="{{ $switchView.RelPermalink }}"
    integrity="{{ $switchView.Data.Integrity }}"
    defer></script>
{{ end }}

完成!

透過郵件回覆
YoZ 柚子
作者
YoZ 柚子
韓國實用音樂系留學生/FOSS Nerd/ISTJ/襯衫、墨鏡愛好者
Hugo Blowfish 主題客製化 - 本文屬於一個選集。
§ 5: 本文

相關文章