网站配置

支持Markdown公式显示 Link to heading

参考 :Hugo+Mathjax的正确姿势

themes\hugo-coder\layouts\partials\extend-head.html

{{ if or .Params.math .Site.Params.math }}
<script>
  MathJax = {
    tex: {
      inlineMath: [['\\(', '\\)']],
      displayMath: [['$$','$$']],
      processEscapes: true,
      processEnvironments: true
    },
    options: {
      skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre']
    }
  };
</script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
{{ end }} 

\themes\hugo-coder\layouts\_default\baseof.html 文件 <head> 标签中,增加一个 extend-head.html 的引入。

{{ partial "extend-head.html" . }}

修改hugo.toml文件,增加math参数,并开启mathjax

# Site parameters
[params]
  #  other params
  math = true  # Enable math support


[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true  
[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true  # This allows HTML in markdown
    [markup.goldmark.extensions]
      [markup.goldmark.extensions.passthrough]
        enable = true
        [markup.goldmark.extensions.passthrough.delimiters]
          block = [['\[', '\]'], ['$$', '$$']]
          inline = [['\(', '\)'], ['$', '$']]

当然,这个math = true/false,可以全站设定,也可以在单个页面中的头部设置。

这里有两个部分,一个部分就是要打开math参数,另一个部分是打开unsafe参数。

有第二个参数,才会允许MathJax处理HTML标签。

定义行间公式时,$$\[\]的前后要留一个空行,不然hugo会忽略任何跟行间公式相连(只有一个换行)的文字。

侧边导航栏 Link to heading

参考:增加侧栏跟随滚动目录 · TsuiDison

将下面的代码保存在/static/js/目录下,命名为toc-sidebar.js

function debounce(func, wait, options = {
  immediate: false,
  middle: true,
  thisArg: null,
}) {
  let timer;
  let restDate = new Date();
  const immediate = options.immediate !== false;
  const middle = options.middle !== false;
  const thisArg = options.thisArg || null;
  return function (...args) {
    timer && clearTimeout(timer);
    let isFirst = !timer;
    timer = setTimeout(() => {
      func.apply(thisArg, args);
      restDate = new Date();
    }, wait);
    if ((new Date() - restDate > wait && middle) || (isFirst && immediate)) {
      clearTimeout(timer);
      func.apply(thisArg, args);
      restDate = new Date();
    }
  }
}

function setActive(anchors) {
  const ele = anchors.find((ele, index, arr) => {
    return ele.getBoundingClientRect().top >= 0 || index >= arr.length - 1;
  });
  if (ele) {
    const tableOfContents = document.querySelector('#table-of-contents');
    const toActive = tableOfContents.querySelector(`a[href="#${ele.id}"]`);
    if (!toActive) return;
    const activeA = tableOfContents.querySelector(`.active`);
    if (activeA) activeA.classList.remove('active');
    toActive.classList.add('active');
    window.history.pushState(null, null, `#${ele.id}`);
    tableOfContents.scrollTo({
      left: 0,
      top: toActive.offsetTop - tableOfContents.getBoundingClientRect().height / 2,
      behavior: 'smooth',
    });
  }
}

function initContents(icon = '<svg t="1690868184633" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3381" width="32" height="32"><path d="M128 192l768 0 0 128-768 0 0-128Z" fill="#666666" p-id="3382"></path><path d="M128 448l768 0 0 128-768 0 0-128Z" fill="#666666" p-id="3383"></path><path d="M128 704l768 0 0 128-768 0 0-128Z" fill="#666666" p-id="3384"></path></svg>') {
  if(document.querySelector('#table-of-contents-wapper')) return;
  const contents = document.createElement('details');
  contents.id = 'table-of-contents-wapper';
  contents.innerHTML = `<summary>
    ${icon}
  </summary>`
  const styleElement = document.createElement('style')
  styleElement.innerHTML = `#table-of-contents-wapper {
    user-select: none;
    position: fixed;
    right: 1em;
    top: 4em;
    border-radius: 8px;
    z-index: 999
  }

  @media only screen and (min-width:768px) {
    #table-of-contents-wapper[open] summary {
      position: relative;
      left: 5.8em
    }

    /* 让文章内容靠左 */
      .content {
        margin-right: 22rem; /* 给右侧预留足够空间 */
        max-width: calc(100% - 25rem);
      }
  }

  @media only screen and (max-width:768px) {
    #table-of-contents-wapper {
      top: auto;
      right: auto;
      bottom: 1.8rem;
      left: 1.8rem
    }
  }

  #table-of-contents-wapper summary {
    display: inline-block;
    font-size: 1.5em;
    border-radius: 4px;
    cursor: pointer;
    padding: .2em
  }

  #table-of-contents-wapper #table-of-contents {
    line-height: 2; /* 增加行高改善可读性 */
    width: 30rem; /* 宽度 */
    font-size: 1.5rem; /* 字号大小 */
    padding: 1em;
    border: 0px solid;
    border-radius: 6px;
    overflow-y: scroll;
    max-height: calc(100vh - 20rem);
    color: currentColor
  }

  #table-of-contents-wapper #table-of-contents a {
    width: 100%;
    display: inline-block;
    color: currentColor;
    line-height: 1; /* 增加行高 */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0.15em; /* 增加上下内边距,让链接更易点击 */
  }

  #table-of-contents-wapper #table-of-contents .active {
    border-left: 2px solid #42a5f5;
    color: #42a5f5
  }

  .content h1,
  .content h2,
  .content h3 {
    padding-top: 2em !important;
    margin-top: -2em !important
  }`;

  const anchors = [...document.querySelector('.content').querySelectorAll('h1[id],h2[id],h3[id],h4[id]')];
  if (!anchors.length) return contents.remove();
  const tableOfContents = document.createElement('div');
  tableOfContents.id = 'table-of-contents';
  anchors.forEach(ele => {
    const a = document.createElement('a');
    if (!ele.innerText) return;
    a.innerText = ele.innerText;
    a.href = `#${ele.id}`;
    a.style.paddingLeft = `${ele.tagName.charAt(1)}em`;
    tableOfContents.appendChild(a);
  });

  contents.appendChild(tableOfContents);
  contents.open = window.innerWidth >= 768;

  document.head.appendChild(styleElement);
  document.body.append(contents);

  setActive(anchors);
  const debounceSetActive = debounce(setActive, 200)
  window.addEventListener('scroll', () => {
    debounceSetActive(anchors);
  });
}

修改footer.htm

对于/layouts/partials/footer.html文件,添加如下代码:

<!-- 用于增加侧栏 -->
<script src="/js/toc-sidebar.js"></script>
<script>
  window.addEventListener('DOMContentLoaded', function() {
    initContents();
  });
</script>

修改网站Icon Link to heading

参考:更改favicon · TsuiDison

生成icon Link to heading

生成icon的两个网站:

对于每一种模版可能需要生成不同样式的icon,对于coder模版,需要以下的icon

  • apple-touch-icon.png
  • favicon-16x16.png
  • favicon-32x32.png
  • favicon.svg

其中,apple-touch-icon.png和favicon.svg可能需要用Realfavicongenerator生成,其他的可以用ico51生成。

替换icon Link to heading

将生成的icon放到/static/images文件夹。

修改hugo.toml文件中icon的相关路径。

  faviconSVG = "/images/favicon.svg"
  favicon_32 = "/images/favicon-32x32.png"
  favicon_16 = "/images/favicon-16x16.png"

如果想要更改显示的图标的尺寸的话可以根据luizdepra的建议去更改/hugo-coder/layouts/partials/head/custom-icons.html的内容。

由于浏览器缓存问题,可能需要强制刷新才能正常显示!!!

修改字体 Link to heading

修改/新建 themes/coder/assets/scss/_variables.scss,添加你想要的 $body-font-family

$font-family: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "Helvetica Neue", sans-serif;

字体应该立即生效