Hugo | 自定义 hugo-theme-Stack

Posted on May 11, 2023
tl;dr:

支持 mermaid,新增导航栏,添加一些小功能,微调样式

修改标题样式

H2 和 H3 区分度不大

image

遂改

image (1)

# /assets/scss/partials/layout/article.scss .article-content {
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    margin-inline-start: calc((var(--card-padding)) * -1);
    padding-inline-start: calc(
      var(--card-padding) - var(--heading-border-size)
    );
  }

  h1,
  h2 {
    border-inline-start: var(--heading-border-size) solid var(--accent-color);
  }

  h3,
  h4,
  h5,
  h6 {
    border-inline-start: var(--heading-border-size) solid #f5f5fa;
  }
}

调整友情链接页面布局

///assets/scss/custom.scss
//友情链接双栏
+ @media (min-width: 1024px) {
+    .article-list--compact.links {
+        display: grid;
+        grid-template-columns: 1fr 1fr;
+        background: none;
+        box-shadow: none;
+
+        article {
+           background: var(--card-background);
+            border: none;
+            box-shadow: var(--shadow-l2);
+            margin-bottom: 8px;
+            border-radius: 10px;
+            &:nth-child(odd) {
+                margin-right: 8px;
+            }
+        }
+    }
+}

代码来自 Hugo | 第三篇 Stack 主题装修记录,堂堂再临!

外部链接的样式

# layouts/_default/_markup/render-link.html

{{ if strings.HasPrefix .Destination "http" }}
<span style="white-space: nowrap;"><svg width=".7em"
    height=".7em" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg">
    <path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" />
    <path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
        fill="currentColor">
</svg></span>
{{ end }}

在移动端显示 TOC

抄了代码 Feature/add inline toc #615

导航栏

隐藏某个选项

隐藏了 Home,和点击 avatar 的效果重复了

.menu {
  li:first-child {
    display: none;
  }
}

新增 menu 选项

/content/page 目录下新建 dairy 文件夹,把 .md 放进来(这些文章不会在 homepage 显示)创建 index.md,在 Tabler Icons 下载 icon 并替换,修改对应的 layout

# layouts/_defualt/list.html
- <div class="section-card">...</div>

+  <section class="article-list">
        {{ range $paginator.Pages }}
+            {{ partial "article-list/default" . }}
        {{ end }}
    </section>

效果:

image-20230614224734155

修改背景色

Open Color 选个喜欢的颜色

# assets\scss\variables.scss
--body-background: #f5f5f5;

禁止部分页面显示 ReadingTime

比如 /friends ,不是文章,不需要显示阅读时间

# /blog/layouts/partials/article/components/details.html

+ {{ if and (not .Date.IsZero) (.Site.Params.article.readingTime) }}

暂时禁用翻译按钮

如果有对应的页面,比如 /page/about 下有:

.
├── index.md
└── index.zh-cn.md

就会显示翻译按钮,暂时用不到的话在 md 文件里写 draft: true即可

添加 mermaid 支持

按照 官方文档 新建文件 layouts/_default/_markup/render-codeblock-mermaid.html

<div class="mermaid">{{- .Inner | safeHTML }}</div>
{{ .Page.Store.Set "hasMermaid" true }}

layouts/partials/article/components/content.html 添加:

{{ .Content | replaceRE "(<table>(?:.|\n)+?</table>)" $wrappedTable | safeHTML }}
{{ if .Page.Store.Get "hasMermaid" }}
  <script type="module">
        import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
        mermaid.initialize({ startOnLoad: true });
  </script>
{{ end }}

演示效果:时序图/饼图/甘特图/Git 图,更多请看 官方文档

sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
pie
    title Pets adopted by volunteers
    "Dogs" : 386
    "Cats" : 85
    "Rats" : 15
gantt
    title A Gantt Diagram
    dateFormat  YYYY-MM-DD
    section Section
    A task           :a1, 2014-01-01, 30d
    Another task     :after a1  , 20d
    section Another
    Task in sec      :2014-01-12  , 12d
    another task      : 24d
gitGraph
   commit
   commit
   branch develop
   checkout develop
   commit
   commit
   checkout main
   merge develop
   commit
   commit

MarkDown 块

固定块的高度

过长的内容影响观感,所以把 block 的高度限制在 20em,并隐藏滚动条

# partials/layout/article.scss
.article-content {
   .highlight {
-     padding: var(--card-padding);
      pre {
        margin: initial;
+       padding: var(--card-padding);
        margin: 0;
        width: auto;
+       max-height: 20em;
+ 			scrollbar-width: none; /* Firefox */
+       &::-webkit-scrollbar {
+         display: none; /* Chrome Safari */
+       }
      }
  }
}

代码块 macOS 样式

# custom.scss .highlight::before {
  content: '';
  display: block;
  background: url(/code-header.svg);
  height: 30px;
  width: 100%;
  background-size: 45px;
  background-repeat: no-repeat;
  margin-bottom: -7px;
  border-radius: 5px;
  background-position: 10px 10px;
  position: absolute;
  top: 0;
  left: 0;
}

修改字体

对样式不满意、就从控制台找到对应的类名,在 custom.scss 里修改就好了

修改正文字体

参照:Example: Custom font family for article content

# layouts/partials/head/custom.html
<style>
  /* Overwrite CSS variable */
  :root {
    --article-font-family: 'Noto Serif HK', var(--base-font-family);
  }
</style>

<script>
  ;(function () {
    const customFont = document.createElement('link')
    customFont.href =
      'https://fonts.googleapis.com/css2?family=Noto+Serif+HK:wght@300;400;500;600;700&display=swap'
    customFont.type = 'text/css'
    customFont.rel = 'stylesheet'

    document.head.appendChild(customFont)
  })()
</script>

修改全站字体

:root {
  --sys-font-family: 'Noto Serif HK', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    'Droid Sans', 'Helvetica Neue';
  --zh-font-family: 'Noto Serif HK', 'Hiragino Sans GB', 'Droid Sans Fallback',
    'Microsoft YaHei';
  --base-font-family: 'Noto Serif HK', var(--sys-font-family);
}

返回顶部按钮

# /layouts/partials/footer/custom.html

<!--返回顶部按钮 -->
<a href="#" id="back-to-top" title="返回顶部"></a>

<!--返回顶部CSS -->
<style>
  #back-to-top {
    display: none;
    position: fixed;
    bottom: 20px;
    right: 55px;
    width: 55px;
    height: 55px;
    border-radius: 7px;
    background-color: rgba(64, 158, 255, 0.5);
    box-shadow: var(--shadow-l2);
    font-size: 30px;
    text-align: center;
    line-height: 50px;
    cursor: pointer;
  }

  #back-to-top:before {
    content: ' ';
    display: inline-block;
    position: relative;
    top: 0;
    transform: rotate(135deg);
    height: 10px;
    width: 10px;
    border-width: 0 0 2px 2px;
    border-color: var(--back-to-top-color);
    border-style: solid;
  }

  #back-to-top:hover:before {
    border-color: #2674e0;
  }

  /* 在屏幕宽度小于 768 像素时,钮位置调整 */
  @media screen and (max-width: 768px) {
    #back-to-top {
      bottom: 20px;
      right: 20px;
      width: 40px;
      height: 40px;
      font-size: 10px;
    }
  }

  /* 在屏幕宽度大于等于 1024 像素时,按钮位置调整 */
  @media screen and (min-width: 1024px) {
    #back-to-top {
      bottom: 20px;
      right: 40px;
    }
  }

  /* 在屏幕宽度大于等于 1280 像素时,按钮位置调整 */
  @media screen and (min-width: 1280px) {
    #back-to-top {
      bottom: 20px;
      right: 55px;
    }
  }

  /* 目录显示时,隐藏按钮 */
  @media screen and (min-width: 1536px) {
    #back-to-top {
      visibility: hidden;
    }
  }
</style>

<!--返回顶部JS -->
<script>
  function backToTop() {
    document.documentElement.scrollIntoView({
      behavior: 'smooth',
    })
  }

  window.onload = function () {
    let scrollTop =
      this.document.documentElement.scrollTop || this.document.body.scrollTop
    let totopBtn = this.document.getElementById('back-to-top')
    if (scrollTop > 0) {
      totopBtn.style.display = 'inline'
    } else {
      totopBtn.style.display = 'none'
    }
  }

  window.onscroll = function () {
    let scrollTop =
      this.document.documentElement.scrollTop || this.document.body.scrollTop
    let totopBtn = this.document.getElementById('back-to-top')
    if (scrollTop < 200) {
      totopBtn.style.display = 'none'
    } else {
      totopBtn.style.display = 'inline'
      totopBtn.addEventListener('click', backToTop, false)
    }
  }
</script>

ShortCodes

内容太长,内容分开存放

添加 apple-touch-icon

# /layouts/_default/baseof.html
<head>
  <link
    rel="apple-touch-icon"
    sizes="180x180"
    href="https://cdn.jsdelivr.net/xxxxxxxx"
  />
</head>

添加背景的蛛网特效

/layouts/_default/baseof.html 引入 <script type="text/javascript" src="https://demo.hellozwh.com/source/canvas-nest.min.js"></script>

!(function () {
  function o(w, v, i) {
    return w.getAttribute(v) || i
  }
  function j(i) {
    return document.getElementsByTagName(i)
  }
  function l() {
    var i = j('script'),
      w = i.length,
      v = i[w - 1]
    return {
      l: w,
      z: o(v, 'zIndex', -1),
      o: o(v, 'opacity', 0.5),
      c: o(v, 'color', '0,0,0'),
      n: o(v, 'count', 99),
    }
  }
  function k() {
    ;(r = u.width =
      window.innerWidth ||
      document.documentElement.clientWidth ||
      document.body.clientWidth),
      (n = u.height =
        window.innerHeight ||
        document.documentElement.clientHeight ||
        document.body.clientHeight)
  }
  function b() {
    e.clearRect(0, 0, r, n)
    var w = [f].concat(t)
    var x, v, A, B, z, y
    t.forEach(function (i) {
      ;(i.x += i.xa),
        (i.y += i.ya),
        (i.xa *= i.x > r || i.x < 0 ? -1 : 1),
        (i.ya *= i.y > n || i.y < 0 ? -1 : 1),
        e.fillRect(i.x - 0.5, i.y - 0.5, 1, 1)
      for (v = 0; v < w.length; v++) {
        x = w[v]
        if (i !== x && null !== x.x && null !== x.y) {
          ;(B = i.x - x.x), (z = i.y - x.y), (y = B * B + z * z)
          y < x.max &&
            (x === f &&
              y >= x.max / 2 &&
              ((i.x -= 0.03 * B), (i.y -= 0.03 * z)),
            (A = (x.max - y) / x.max),
            e.beginPath(),
            (e.lineWidth = A / 2),
            (e.strokeStyle = 'rgba(' + s.c + ',' + (A + 0.2) + ')'),
            e.moveTo(i.x, i.y),
            e.lineTo(x.x, x.y),
            e.stroke())
        }
      }
      w.splice(w.indexOf(i), 1)
    }),
      m(b)
  }
  var u = document.createElement('canvas'),
    s = l(),
    c = 'c_n' + s.l,
    e = u.getContext('2d'),
    r,
    n,
    m =
      window.requestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.oRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function (i) {
        window.setTimeout(i, 1000 / 45)
      },
    a = Math.random,
    f = { x: null, y: null, max: 20000 }
  u.id = c
  u.style.cssText =
    'position:fixed;top:0;left:0;z-index:' + s.z + ';opacity:' + s.o
  j('body')[0].appendChild(u)
  k(), (window.onresize = k)
  ;(window.onmousemove = function (i) {
    ;(i = i || window.event), (f.x = i.clientX), (f.y = i.clientY)
  }),
    (window.onmouseout = function () {
      ;(f.x = null), (f.y = null)
    })
  for (var t = [], p = 0; s.n > p; p++) {
    var h = a() * r,
      g = a() * n,
      q = 2 * a() - 1,
      d = 2 * a() - 1
    t.push({ x: h, y: g, xa: q, ya: d, max: 6000 })
  }
  setTimeout(function () {
    b()
  }, 100)
})()

有兴趣了做做

✅ 博客时间轴

  • 导航页

参考 & 致谢

Hugo | 看中 Stack 主题的归档功能,搬家并做修改

Hugo Stack 主题折腾笔记

拥抱最好用的 hugo 之 stack

『Hugo』Hugo Styles

来写一些好玩的 Hugo 短代码吧

Hugo Stack 主题装修笔记 Hugo 博客自定义优化