使用Hugo框架搭建博客的过程 - 功能拓展
前言
本文介绍一些拓展功能,如文章页面功能增加二级菜单,相关文章推荐和赞赏。另外,使用脚本会大大简化写作后的上传流程。
文章页面功能
这部分功能的拓展主要是用前端的JS和CSS,如果对前端不了解,可以参考放在Github上的网站源码。
二级菜单
导航栏放都太多链接不分主次,不够简洁。尝试多种方案后,做出了现在的二级菜单。
- 使用bootstrap框架
引入了太多样式,界面被扰乱,不够友好。 - Select标签
样式单一,不能修改。 - Hover属性
多个二级菜单不能使用相同参数的绝对定位,拓展太麻烦。
最终方案是:引入Jquery,使用Jquery的slideToggle()方法。可拓展,不影响原有界面。步骤如下。
- 调整下拉菜单的样式
/* 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*/
- 调用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;
}
- 修改菜单模板,详细代码参考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 -}}
- 菜单配置,子菜单设置
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
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;">「 {{- T "thanksSponsor" -}} 」</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>
T和i18n函数是翻译函数,按照不同的语言,使用对应语言的字符串。参考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
。
文章同步到服务器的步骤如下。
- 本地创建博客文章
- 配置SSH免密登陆
- 使用Python脚本生成网站静态资源,提交变更
- 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
命令,确定服务器同步是否正常。
代码改变世界,现在,写作多么简单。
参考
使用Hugo框架搭建博客的过程 - 功能拓展的更多相关文章
- 使用Hugo框架搭建博客的过程 - 页面模板
前言 最初在制作友链界面时,没有学习Hugo框架,一头雾水.网上有关的教程甚少,只能去学一遍Hugo. 在学习Hugo的过程中,了解了列表模板,分类模板.开发了几个功能页面,如:留言板,友链,记忆分类 ...
- 使用Hugo框架搭建博客的过程 - 前期准备
前言 这篇教程介绍了如何搭建这样效果的博客. 所需步骤 可以从这样的角度出发: 注册域名. 使用CDN加快网站访问速度. 网站内容需要部署在服务器或对象存储平台上. 重要的是放什么内容.博客需要选择框 ...
- 使用Hugo框架搭建博客的过程 - 主题配置
前言 博客部署完成后,恭喜你可以发表第一篇:Hello world!但是LoveIt这么好用的主题,不配置一番可惜了. 基本功能配置 主题配置最好参考已有的配置,比如LoveIt作者写的介绍,还有主题 ...
- 使用Hugo框架搭建博客的过程 - 部署
前言 完成前期的准备工作后,在部署阶段需要配置服务器或对象存储服务. 对象存储和服务器对比 对象存储平台 国内有阿里云OSS.腾讯COS.又拍云.七牛云等.国外有Github Pages.Netlif ...
- 用 Hugo 快速搭建博客
用 Hugo 搭建博客 Hugo 是一个用 Go 编写的静态站点生成器,生成速度很快 下面是具体操作: 1.安装 Hugo Windows 用户 使用 Chocolatey 或者 Scoop 快速安装 ...
- 在Windows下使用Hexo+GithubPage搭建博客的过程
1.安装Node.js 下载地址:传送门 去 node.js 官网下载相应版本,进行安装即可. 可以通过node -v的命令来测试NodeJS是否安装成功 2.安装Git 下载地址:传送门 去 Git ...
- 使用Hexo框架搭建博客,并部署到github上
开发背景:年后回来公司业务不忙,闲暇时间了解一下node的使用场景,一篇文章吸引了我15个Nodejs应用场景,然后就被这个hexo框架吸引了,说时迟,那时快,赶紧动手搭建起来,网上找了好多资料一天时 ...
- Hugo hexo 搭建博客系列1:自己的服务器
hexo jekyll https://hexo.io/zh-cn/ http://theme-next.iissnan.com/getting-started.html Hexo 是高效的静态站点生 ...
- hugo + nginx 搭建博客记录
作为一个萌新Gopher,经常逛网站能看到那种极简的博客,引入眼帘的不是花里胡哨的图片和样式,而是黑白搭配,简简单单的文章标题,这种风格很吸引我.正好看到煎鱼佬也在用这种风格的博客,于是卸载了我的wo ...
随机推荐
- 行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug
根据外媒 9to5 Google 报道,3 月 23 日几个小时内,大量安卓用户遇到一些安卓应用连续闪退的情况,有人发现卸载安卓系统 WebView 就可以停止闪退.目前,谷歌已经发布了应用崩溃问题的 ...
- ASP.NET Core文件上传IFormFile于Request.Body的羁绊
前言 在上篇文章深入探究ASP.NET Core读取Request.Body的正确方式中我们探讨了很多人在日常开发中经常遇到的也是最基础的问题,那就是关于Request.Body的读取方式问题,看是简 ...
- .Net Core gRPC 实战(二)
概述 gRPC 客户端必须使用与服务相同的连接级别安全性. 如调用服务时通道和服务的连接级别安全性不一致,gRPC 客户端就会抛出错误. gRPC 配置使用HTTP gRPC 客户端传输层安全性 ( ...
- Python+Selenium自动化-清空输入框、输入内容、点击按钮
Python+Selenium自动化-清空输入框.输入内容.点击按钮 1.输入内容 send_keys('valve'):输入内容valve #定位输入框 input_box = browser. ...
- GO语言面向对象05---接口的多态
package main import "fmt" type Fighter interface { Attack() (bloodloss int) Defend() } /*骑 ...
- MindSpore平台系统类
MindSpore平台系统类 Q:MindSpore只能在华为自己的NPU上跑么? A: MindSpore同时支持华为自己的Ascend NPU.GPU与CPU,是支持异构算力的. Q:MindSp ...
- 激光雷达lidar与点云数据
激光雷达lidar与点云数据 DEM是分布和显示数字地形的首个广泛使用的机制. 点云是在空间中随机放置的3D点的集合.传感器发出能量脉冲并乘以其返回行程(TWTT,双向行程时间).知道了传感器的位置以 ...
- Wide-Bandgap宽禁带(WBG)器件(如GaN和SiC)市场将何去何从?
Wide-Bandgap宽禁带(WBG)器件(如GaN和SiC)市场将何去何从? Where Is the Wide-Bandgap Market Going? 电力电子在采用宽禁带(WBG)器件(如 ...
- 解决:ImportError: DLL load failed while importing _sqlite3: 找不到指定的模块。
Django框架学习第一步,创建一个Django工程. 本次采用的是创建虚拟环境来创建Django工程.本地解释器采用anaconda ,内置Python3.8 在pycharm中报错: 内容如下:I ...
- 使用fiddler工具模拟弱网环境
1.使用CTRL+R快捷键调出设置窗口 2.CTRL+F搜索"if (m_SimulateModem)",如下图 3.设置 // 这里修改每KB上传时候的延迟速度,以ms为单位 ...