使用Hugo框架搭建博客的过程 - 功能拓展
阅读原文时间:2023年07月09日阅读:2

本文介绍一些拓展功能,如文章页面功能增加二级菜单,相关文章推荐和赞赏。另外,使用脚本会大大简化写作后的上传流程。

这部分功能的拓展主要是用前端的JS和CSS,如果对前端不了解,可以参考放在Github上的网站源码

二级菜单

导航栏放都太多链接不分主次,不够简洁。尝试多种方案后,做出了现在的二级菜单。

  1. 使用bootstrap框架

    引入了太多样式,界面被扰乱,不够友好。

  2. Select标签

    样式单一,不能修改。

  3. Hover属性

    多个二级菜单不能使用相同参数的绝对定位,拓展太麻烦。

最终方案是:引入Jquery,使用Jquery的slideToggle()方法。可拓展,不影响原有界面。步骤如下。

  1. 调整下拉菜单的样式

    /* dropdown menus css*/
    .dropdown {
    position: relative;
    display: inline;
    margin: 0px;
    }

    .dropdown-menu {
    position: absolute;
    left: 0;
    z-index: 1000;
    float: left;
    min-width: auto;
    padding: 2px 1px;
    font-size: 14px;
    text-align: left;
    list-style: none;
    background-color: #fff;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
    border: 1px solid #ccc;
    border-radius: 4px;
    -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
    box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
    }

    .dropdown-menu-mobile {
    width: 100%;
    position: relative;
    background: transparent;
    text-align: center;
    }

    .dropdown-menu.show {
    display: block;
    }

    .dropdown-item {
    display: block;
    margin: .4rem 0.5rem;
    clear: both;
    font-weight: 400;
    color: #212529;
    text-align: inherit;
    white-space: nowrap;
    background-color: transparent;
    line-height: 1.5rem;
    }

    .btn {
    vertical-align: inherit;
    font-weight: 400;
    color: #212529;
    text-align: center;
    -webkit-user-select: none;
    user-select: none;
    background-color: transparent;
    font-size: 1rem;
    border-radius: .25rem;
    }
    /* dropdown menus css*/

  2. 调用JS

    $(".dropdown").each(function() {
    $(this).on("click", function(e) {
    // 收起其他菜单
    if (isMobile()) {
    $(".menu").find(".dropdown-menu").not($(this).children("div")).slideUp("fast");
    } else {
    $(".menu-inner").find(".dropdown-menu").not($(this).children("div")).slideUp("fast");
    }
    e.stopPropagation();
    var downmenu = $(this).children("div");
    // 展开菜单
    downmenu.slideToggle("fast");
    // 点击其他地方,隐藏菜单
    if (downmenu.is(":visible")) {
    $(document).one("click", function() {
    downmenu.slideUp("fast");
    });
    }
    });
    });

    移动端

    function isMobile(){
    return window.matchMedia("only screen and (max-width: 680px)").matches;
    }

  3. 修改菜单模板,详细代码参考header.html

  4. 菜单配置,子菜单设置parent属性指向父菜单。

    [languages.en.menu]
    [[languages.en.menu.main]]
    identifier = "home"
    pre = ""
    post = ""
    name = "Home"
    url = ""
    title = "Home"
    weight = 1

    [[languages.en.menu.main]]
        identifier = "posts"
        pre = "<i class='fas fa-archive fa-fw'></i>"
        post = ""
        name = "Posts"
        url = "posts/"
        title = "all articles"
        weight = 2
    
    [[languages.en.menu.main]]
        identifier = "memory"
        pre = "<i class='fas fa-database fa-fw'></i>"
        post = ""
        name = "Memory"
        url = "memories/"
        title = "left it"
        weight = 3
    
    [[languages.en.menu.main]]
        identifier = "tags"
        pre = "<i class='fas fa-tags fa-fw'></i>"
        post = ""
        name = " Tags"
        url = "tags/"
        title = ""
        weight = 4
    
    [[languages.en.menu.main]]
        identifier = "categories"
        pre = "<i class='fas fa-th-list fa-fw'></i>"
        post = ""
        name = "Categories"
        url = "categories/"
        title = ""
        weight = 5
    
    [[languages.en.menu.main]]
        identifier = "share"
        pre = "<i class='fas fa-fan fa-fw'></i>"
        post = ""
        name = "Share"
        title = ""
        weight = 7
    
    [[languages.en.menu.main]]
        identifier = "books"
        pre = "<i class='fas fa-file-alt fa-fw'></i>"
        post = ""
        name = "Book list"
        url = "booklist/"
        title = ""
        weight = 8
        parent = "share"
    
    [[languages.en.menu.main]]
        identifier = "websites"
        pre = "<i class='fas fa-globe fa-fw'></i>"
        post = ""
        name = "Websites"
        url = "websites/"
        title = ""
        weight = 8
        parent = "share"
    
    [[languages.en.menu.main]]
        identifier = "internal"
        pre = "<i class='fas fa-door-closed fa-fw'></i>"
        post = ""
        name = "Doors"
        title = ""
        weight = 8
    
    [[languages.en.menu.main]]
        identifier = "message-board"
        pre = "<i class='fas fa-comments fa-fw'></i>"
        post = ""
        name = "Message Board"
        url = "message-board/"
        title = ""
        weight = 8
        parent = "internal"
    
    [[languages.en.menu.main]]
        identifier = "favorites"
        pre = "<i class='fas fa-star fa-fw'></i>"
        post = ""
        name = "Favorites"
        url = "favorites/"
        title = ""
        weight = 8
        parent = "internal"
    
    [[languages.en.menu.main]]
        identifier = "milestone"
        pre = "<i class='fas fa-monument fa-fw'></i>"
        post = ""
        name = "Milestone"
        url = "milestone/"
        title = ""
        weight = 8
        parent = "internal"
    
    [[languages.en.menu.main]]
        identifier = "links"
        pre = "<i class='fas fa-user-friends fa-fw'></i>"
        post = ""
        name = "Links"
        url = "links/"
        title = ""
        weight = 9
        parent = "internal"
    
    [[languages.en.menu.main]]
        identifier = "about"
        pre = "<i class='fas fa-user-secret fa-fw'></i>"
        post = ""
        name = "About"
        url = "about/"
        title = ""
        weight = 10
        parent = "internal"

相关文章推荐

参考Related Content

themes\LoveIt\layouts\posts\single.html添加以下代码:

{{- /*see also*/ -}}
# 显示tag分类相关的前5篇文章
{{ $related := .Site.RegularPages.RelatedIndices . "tags" | first 5 }}
{{ with $related }}
    <div id="related-article">
        <p>{{- T "seeAlso" -}}</p>
        <ul>
            {{ range . }}
            <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
            {{ end }}
        </ul>
    </div>
{{ end }}

赞赏

赞赏功能需要在data\imgURL.toml中添加图片的URL。

alipay = "https://img.xiaodejiyi.com/img/alipay.jpg"
weichatPay = "https://img.xiaodejiyi.com/img/wechat%20pay.jpg"

然后在模板文件themes\LoveIt\layouts\posts\single.html添加以下代码:

{{- /* sponsor */ -}}
<div style="text-align:center;margin-bottom:30px;">
    <h5 style="font-weight:600;margin-bottom:10px;">「&nbsp;{{- T "thanksSponsor" -}}&nbsp;」</h5>
    <button id="rewardButton"><span>{{- T "tips" -}}</span></button>
    <div id="QR" style="display: none;">
        <div id="wechat" style="display:inline-block">
            <a class="fancybox" rel="group">
                <img id="wechat_qr" src="{{ .Site.Data.imgURL.weichatPay }}" alt="WeChat Pay"></a>
            <h5 style="font-weight:600;margin-top:5px;">{{- T "weichatTip" -}}</h5>
        </div>
        <div id="alipay" style="display: inline-block">
            <a class="fancybox" rel="group">
                <img id="alipay_qr" src="{{ .Site.Data.imgURL.alipay }}" alt="Alipay"></a>
            <h5 style="font-weight:600;margin-top:5px;">{{- T "aliTip" -}}</h5>
        </div>
    </div>
</div>

Ti18n函数是翻译函数,按照不同的语言,使用对应语言的字符串。参考i18n

版权声明

themes\LoveIt\layouts\posts\single.html添加以下代码:

{{- /*copyright*/ -}}
<div id="copyright-container">
    <ul class="post-copyright">
        <li class="post-copyright-author">
            <strong>{{- T "articleAuthor" -}}:</strong><a href="{{ $.Site.Author.link | default .Site.Home.RelPermalink }}" target="_blank">{{ T "penname" }}</a>
        </li>
        <li class="post-copyright-link">
            <strong>{{- T "articleLink" -}}:</strong><a href="#" target="_blank" title="{{ .Title }}">{{- .Permalink | safeHTML -}}</a>
        </li>
        <li class="post-copyright-license">
            <strong>{{- T "copyRight" -}}:</strong>
            {{- $prestr := printf `<a href="%v" target="_blank" title="CC BY-NC-ND 4.0">%v</a>` .Site.Params.footer.license ( T "license" ) -}}
            {{- $laststr := printf `<a href="%v" target="_blank">%v</a>` ($.Site.Author.link | default .Site.Home.RelPermalink) ( T "penname" ) -}}
        {{- dict "preCopyRight" $prestr "afterCopyRight" $laststr | T "copyRightMsg" | safeHTML }}
        </li>
    </ul>
</div>

需要使用T函数翻译并且根据不同语言传递参数。

[copyRightMsg]
other = "本站所有文章除特别声明外,均采用 {{ .preCopyRight }} 转载请注明来自 {{ .afterCopyRight }} "

.Site.Params.footer.license在config.toml中设置:license = 'https://creativecommons.org/licenses/by-nc-sa/4.0/'

如果需要了解同步文章到对象存储平台,请参考Hugo 静态网站部署及免费 HTTPS 证书配置OSS常用工具汇总

文章最后的“阅读全文”可以绕过,方法是在Chrome控制台的Network中找到readmore.js,右键Block request URL

文章同步到服务器的步骤如下。

  1. 本地创建博客文章
  2. 配置SSH免密登陆
  3. 使用Python脚本生成网站静态资源,提交变更
  4. Github Action使用rsync同步网站静态资源到服务器,并使用atomic-algolia同步index.json到Algolia。

创建文章

archetypes目录下的创建模板文件,使用hugo new --kind post-bundle posts/my-post生成指定模板的样例文章,不需要每次复制文章头部参数。

archetypes\post-bundle\index.md文件内容

SSH免密登陆

注意!服务器端要配置authorized_keys。参考设置 SSH 通过密钥登录

注册Algolia

使用Algolia搜索引擎为博客提供搜索功能。参考搜索配置

本地同步与备份脚本

在博客目录下执行该脚本,先推送blog到Github的blog仓库,再本地备份。(相信看到这里的读者都有Github帐号了)

import time
import os, sys

def main(msg):
    # 备份blog/
    print("*"*10+"push blog/"+"*"*10, end="\n\n")
    # 生成静态页面
    os.system('hugo')

    # 需要安装Git
    os.system('git add .')
    os.system('git commit -m "{}"'.format(msg))
    os.system('git push')

    local_back = input('\n本地备份?提示: y\n')
    if local_back == 'y':
        #7z、winrar压缩参数是一样的,只有winrar的话,7z换成winrar也可以运行
        os.system(r'7z a D:\src\xxxxx.rar D:\src\xxxxx')
        os.system(r'move D:\src\code\xxxxx.rar D:\backup\xxxxx')
        print('本地备份完成!')

    print('over...')

if __name__ == '__main__':
    msg = input('commit: ')
    main(msg)

如果需要安装Git,试试Scoop,它用来安装应用程序非常方便。

Github Action

blog/文件根目录下创建package.json文件,并在scripts模块中加入"algolia": "atomic-algolia"

{
  "name": "algolia",
  "version": "0.2.0",
  "description": "atomic-algolia package",
  "private": true,
  "scripts": {
    "algolia": "atomic-algolia"
  }
}

在Github的Blog仓库中添加Secrets变量

同步index.json到Algolia需要配置如下变量:

  • ALGOLIA_ADMIN_KEY
  • ALGOLIA_APP_ID
  • ALGOLIA_INDEX_NAME

rsync同步需要配置如下变量

  • HOST

  • PORT

  • USER

  • REMOTE_PATH

    Nginx中配置的网站根目录

  • SSH_KEY

使用Github Action,创建workflow,复制以下代码。

name: deploy_blog

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Check Out
        uses: actions/checkout@v2

      #同步blog搜索
      - name: Use Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '12.x'

      - name: Install automic-algolia
        env:
          ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
          ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }}
          ALGOLIA_INDEX_NAME: zh-cn
          ALGOLIA_INDEX_FILE: "./public/index.json"
        run: |
          npm install atomic-algolia
          npm run algolia

        # 同步英语文章的json
      - name: en json
        env:
          ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
          ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }}
          ALGOLIA_INDEX_NAME: en
          ALGOLIA_INDEX_FILE: "./public/en/index.json"
        run: |
          npm run algolia

      - name: deploy to server
        uses: AEnterprise/rsync-deploy@v1.0
        env:
          DEPLOY_KEY: ${{ secrets.SSH_KEY }}
          # avzr参数,增量备份本地文件。-delete 删除目标地址中本地没有的文件
          ARGS: "-avzr --delete"
          SERVER_PORT: ${{ secrets.PORT }}
          FOLDER: "./public/"
          SERVER_IP: ${{ secrets.HOST }}
          USERNAME: ${{ secrets.USER }}
          SERVER_DESTINATION: ${{ secrets.REMOTE_PATH }}

如果出现问题,先在本地创建linux虚拟机,测试rsync命令,确定服务器同步是否正常。

代码改变世界,现在,写作多么简单。