zoukankan      html  css  js  c++  java
  • 使用Hugo框架搭建博客的过程

    前言

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

    文章页面功能

    这部分功能的拓展主要是用前端的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- 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 {
         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*/
    
    1. 调用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- 680px)").matches;
    }
    
    1. 修改菜单模板,详细代码参考header.html
    <div class="menu" style="overflow: visible">
        <div class="menu-inner">
            {{- range .Site.Menus.main -}}
    
                {{- /* MultiMenus */ -}}
                {{ if .HasChildren }}
                    <div class="dropdown menu-item" style="display: inline;">
                        <a class="btn" href="javascript:void(0);" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{- .Pre | safeHTML }}{{ .Name }}{{ .Post | safeHTML -}}</a>
                        <div class="dropdown-menu" style="display: none;">
                        {{ range .Children }}
                            {{- $url := .URL | relLangURL -}}
                            {{- with .Page -}}
                                {{- $url = .RelPermalink -}}
                            {{- end -}}
                            <a class="dropdown-item" href="{{ $url }}" {{ if (urls.Parse $url).Host }} rel="noopener noreffer" target="_blank"{{ end }}>{{- .Pre | safeHTML }} {{ .Name }} {{ .Post | safeHTML -}}</a>
                        {{ end }}
                        </div>
                    </div>                       
                {{ else }}
                    {{- $url := .URL | relLangURL -}}
                    {{- with .Page -}}
                        {{- $url = .RelPermalink -}}
                    {{- end -}}
                    <a class="menu-item{{ if $.IsMenuCurrent `main` . | or ($.HasMenuCurrent `main` .) | or (eq $.RelPermalink $url) }} active {{ end }}" href="{{ $url }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if (urls.Parse $url).Host }} rel="noopener noreffer" target="_blank"{{ end }}>                            {{- .Pre | safeHTML }}{{ .Name }}{{ .Post | safeHTML -}}</a>
                {{ end }}
            {{- end -}}
    
    {{- /* Mobile header */ -}}
    {{- range .Site.Menus.main -}}
        {{- /* MultiMenus */ -}}
        {{ if .HasChildren }}
            <div class="dropdown menu-item">
                <a class="btn" href="javascript:void(0);" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{- .Pre | safeHTML }}{{ .Name }}{{ .Post | safeHTML -}}</a>
                <div class="dropdown-menu dropdown-menu-mobile" style="display: none">
                {{ range .Children }}
                    {{- $url := .URL | relLangURL -}}
                    {{- with .Page -}}
                        {{- $url = .RelPermalink -}}
                    {{- end -}}
                    <a class="dropdown-item" href="{{ $url }}" {{ if (urls.Parse $url).Host }} rel="noopener noreffer" target="_blank"{{ end }}>{{- .Pre | safeHTML }} {{ .Name }} {{ .Post | safeHTML -}}</a>
                {{ end }}
                </div>
            </div>                       
        {{ else }}
            {{- $url := .URL | relLangURL -}}
            {{- with .Page -}}
                {{- $url = .RelPermalink -}}
            {{- end -}}
            <a class="menu-item" href="{{ $url }}" title="{{ .Title }}"{{ if (urls.Parse $url).Host }} rel="noopener noreffer" target="_blank"{{ end }}>
                {{- .Pre | safeHTML }}{{ .Name }}{{ .Post | safeHTML -}}
            </a>
        {{ end }}
        {{- end -}}
    
    1. 菜单配置,子菜单设置parent属性指向父菜单。
      [languages.en.menu]
          [[languages.en.menu.main]]
            identifier = "home"
            pre = "<i class='fas fa-home fa-fw'></i>"
            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
    themesLoveItlayoutspostssingle.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 }}
    

    赞赏

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

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

    然后在模板文件themesLoveItlayoutspostssingle.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

    版权声明

    themesLoveItlayoutspostssingle.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生成指定模板的样例文章,不需要每次复制文章头部参数。

    archetypespost-bundleindex.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="
    
    ")
    	# 生成静态页面
    	os.system('hugo')
    
        # 需要安装Git
    	os.system('git add .')
    	os.system('git commit -m "{}"'.format(msg))
    	os.system('git push')
    
        local_back = input('
    本地备份?提示: y
    ')
        if local_back == 'y':
            #7z、winrar压缩参数是一样的,只有winrar的话,7z换成winrar也可以运行
            os.system(r'7z a D:srcxxxxx.rar D:srcxxxxx')
            os.system(r'move D:srccodexxxxx.rar D:ackupxxxxx')
            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命令,确定服务器同步是否正常。

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

    参考

  • 相关阅读:
    CXF整合Spring之JaxWsProxyFactoryBean调用
    js代码判断浏览器种类IE、FF、Opera、Safari、chrome及版本
    Python hypot() 函数
    Python cos() 函数
    Python atan2() 函数
    Python asin() 函数
    Python atan() 函数
    Python acos() 函数
    Python uniform() 函数
    Python shuffle() 函数
  • 原文地址:https://www.cnblogs.com/langyao/p/14285898.html
Copyright © 2011-2022 走看看