前言
本文介紹一些拓展功能,如文章頁面功能增加二級菜單,相關文章推薦和贊賞。另外,使用腳本會大大簡化寫作后的上傳流程。
文章頁面功能
這部分功能的拓展主要是用前端的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
命令,確定服務器同步是否正常。
代碼改變世界,現在,寫作多么簡單。