部落格開發日誌 0x02

Admonition

我把 Material for MkDocs - Admonition Extension 搬過來啦,因為實在太好看,就搬過來用了,並且做了下面兩個小改動

  1. border-radius 拔掉了,還是方的好看
  2. 陰影改淡了,感覺比較對
example

這是範例

note

這是範例

abstract

這是範例

info

這是範例

tip

這是範例

success

這是範例

question

這是範例

warning

這是範例

failure

這是範例

danger

這是範例

quote

這是範例

實作

hexo-tag-admonition 借 code 過來改
基本上就是 register 一個新的 hexo tag,然後用到了 detailssummary 這兩個 html5 新的 tag
改的時候有幾個小地方要注意

  1. details tag 原本就有一個箭頭但是很醜,在 summary::-webkit-details-marker 設定 display:none 拔掉他
  2. icon 用到了 font-family: Material Icons,要在 head 裡面加個字體

Highlight

另一個改動是程式碼區塊的部分,原來的有點小醜,就改了幾下

  1. 沒有給檔名就不要顯示上面的 header
  2. 可以指定起始行數,以及指定標記特定行數,如下範例
1
python run.py >3,6
run.py >3,6
1
2
3
4
5
6
import math

def main():
print(f'test {math.factorial(5)}')

main()

部落格開發日誌 0x01

部落格架好後,趁熱使用一下各種網站追蹤評測的工具,比如 Google Search Console, Google Analytics, PageSpeed Insights, Sitechecker, Hotjar

Hotjar

記錄使用者點擊的 heatmap

記錄使用者游標移動的路徑

還可以收集使用者的 feedback 回饋,不過載入時間有點久,部落格也不太需要這些資訊,所以就拔掉了,試用一下而已xD

SEO

Defer offscreen images

參考 Lazy load offscreen images with lazysizes,只要載入 lazysizes 這個 scripts 進來,然後把 src 改成 data-src 並加上 class="lazyload" 就好了

註冊個 hexo 的 after_render,把所有 img tag 抓出來改就完事了

scripts/lazy-load-image.js
1
2
3
hexo.extend.filter.register('after_render:html', function (htmlContent) {
return htmlContent.replace(/<img src="([^"]*)" (?:class="([^"]*)")?([^>]*)>/, '<img data-src="$1" class="$2 lazyload" $3>')
});

lazysizes 有 cdn,很方便的

layout/common/scripts.ejs
1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.0/lazysizes.min.js" defer></script>

Sitemap

1
npm install hexo-generator-sitemap

裝好 hexo-generator-sitemap 之後,在 _config.yml 加一行收工

1
2
sitemap:
path: sitemap.xml

Robots.txt

直接放在 source/_posts 下面就行了,簡單搞定

部落格開發日誌 0x00

之前的部落格是用 mkdocs,但是 mkdocs 其實是用來生成 document 的,不是拿來生成部落格的,所以文章都沒有日期,也沒有近期文章或是標籤的功能,我之所以選 mkdocs 是因為 mkdocs-material 實在太好看了很對我胃口,不過最近興起了想幫部落格換個皮的念頭,主要是看上了 icarusmaterial-x 這兩個主題,都是 hexo 的主題,最後選了 icarus,然後再自己手動調整,下面會說明一下我手動調整的內容

排版

這個主題整體來說很好看的,但是我不喜歡他的排版,文章只能擠在中間細細長長的,左右兩邊還留了很多空隙,不知道是作者的螢幕太小還是我螢幕太大,所以我把所有 widget 都移到左邊,然後把欄位的比例改成 3:9,css 的部份在 source/css/style.styl:21 把寬度調寬

layout/layout.ejs
1
2
case 2:
return 'is-9-tablet is-9-desktop is-9-widescreen';
layout/common/widget.ejs
1
2
case 2:
return 'is-3-tablet is-3-desktop is-3-widescreen';
source/css/style.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
gap = 40px
...
@media screen and (min-width: screen-widescreen)
.is-1-column .container
.is-2-column .container
max-width: screen-widescreen - 2 * gap
width: screen-widescreen - 2 * gap
@media screen and (min-width: screen-fullhd)
.is-2-column .container
max-width: screen-fullhd - 2 * gap
width: screen-fullhd - 2 * gap
.is-1-column .container
max-width: screen-fullhd - 2 * gap
width: screen-fullhd - 2 * gap

Read More

原本 icarus 只有 excerpt 這個選項可以加在文章的 front-matter 中,如下

1
2
3
4
---
title: "部落格開發日誌"
excerpt: 寫一些摘要在這邊
---

但是要每一篇都要自己寫摘要好麻煩,我比較想要的是只顯示固定長度,然後邊邊模糊處理,所以就自己手刻了一個

layout/common/article.ejs
1
2
3
4
5
6
7
8
<div class="card <%= index && (!post.hasOwnProperty('readmore') || post.readmore) ? 'card-readmore' : '' %>">
...
<% if (index && (!post.hasOwnProperty('readmore') || post.readmore)) { %>
<div class="level is-mobile readmore-button">
...
</div>
<% } %>
...
source/css/style.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.card-readmore
max-height: 400px
overflow: hidden
position: relative
.readmore-button
position absolute
left: 0
bottom: 20px
width: 100%
display: flex
justify-content center
z-index: 20
&:after
content: ''
position: absolute
bottom: 60px
width: 100%
height: 100px
z-index: 10
background-image: linear-gradient(to bottom, hsla(0, 100%, 100%, 0), hsla(0, 100%, 100%, 0.9))
&:before
content: ''
position: absolute
bottom: 0
width: 100%
height: 60px
z-index: 10
background-image: linear-gradient(to bottom, hsla(0, 100%, 100%, 0.9), hsla(0, 100%, 100%, 1))

Adblock

我本身有在用 AdBlock,然後在用 icarus 主題的時候發現有些物件會憑空消失,比如 back-to-top 那個按了可以回到頁面頂端的小按鈕,後來發現是被 AdBlock 砍了,因為那個小按鈕有 .back-to-top 這個 class,不只 .back-to-top 還有很多關鍵字會被砍,可以看這份 Class and ID to avoid because of AdBlock,那我的解決辦法就是把原始碼裡所有的 back-to-top 改名成 bottom-to-top

就在剛剛,我寫完第一段之後,發現上面的 h2 標題 Adblock 因為 markdown 生成 html 時自動加了 id=Adblock,然後就被 AdBlock 砍了,只好改成自己手刻 html

1
<h2>Adblock</h2>

另一個被砍掉的是 font-awesome 的 icon .fa-instagram,這個就不好改名了,所以我加了一小行 javascript 把 .fa-ig 改成 .fa-instagram,以結果來看我的 script 跑的順序應該是比 AdBlock 來得後面所以沒有被砍

source/js/main.js
1
2
3
4
$(document).ready(function() {
$('.fa-ig').addClass('fa-instagram');
$('.fa-ig').removeClass('fa-ig');
});

Github

mkdocs-material 主題的右上角有顯示 github star 的功能,我覺得很酷,所以就搬過來了

layout/common/navbar.ejs
1
2
3
4
5
6
<a class="navbar-item github-source" href="<%= github.url %>">
<div class="github-source-icon"><i class="fab fa-lg fa-github-alt"></i></div>
<div class="github-source-repository">
<%= github.name %>
</div>
</a>
source/css/style.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.github-source
.github-source-icon
padding: 5px
.github-source-repository
padding-left: 10px
font-size: 10px
font-weight: 1000
ul
animation: animateElement linear .3s;
animation-iteration-count: 1;
li
float: left
font-weight: 200
#github-forks
margin-left: 3px

@keyframes animateElement{
0% {
opacity:0;
transform: translate(0px,10px);
}
100% {
opacity:1;
transform: translate(0px,0px);
}
}
source/js/main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
if (typeof (IcarusThemeSettings) !== 'undefined' &&
typeof (IcarusThemeSettings.github.url) !== 'undefined') {
const url = IcarusThemeSettings.github.url
console.log(url)
const matches = /^.+github\.com\/([^/]+)\/?([^/]+)?.*$/.exec(url)
console.log(matches)
if (matches && matches.length === 3) {
const [, user, name] = matches
console.log(user, name)
const api = `https://api.github.com/users/${user}/repos`
const paginate = (page = 0) => (
fetch(`${api}?per_page=100&sort=updated&page=${page}`)
.then(response => response.json())
.then(data => {
if (!(data instanceof Array))
return []

/* Display number of stars and forks, if repository is given */
if (name) {
const repo = data.find(item => item.name === name)
if (!repo && data.length === 30) return paginate(page + 1)

if (typeof repo.stargazers_count !== 'number' || typeof repo.forks_count !== 'number') return []
/* If we found a repo, extract the facts */
return repo
? [
`${repo.stargazers_count} Stars`,
`${repo.forks_count} Forks`
]
: []

/* Display number of repositories, otherwise */
} else {
return [
`${data.length} Repositories`
]
}
})
)
paginate().then(data => {
console.log(data)
const [stars, forks] = data
const facts = $(`<ul class="github-facts"><li id="github-stars">${stars}</li><li id="github-forks">• ${forks}</li></ul>`)
$('.github-source-repository').append(facts)
})
}
}

舊部落格

舊的部落格我還在慢慢搬移當中,所以我把 mkdocs 生成的 html 放進來 hexo 當 static files,只要放在 source/old/ 底下然後在 _config.yml 裡面加一行 skip_render: old/**,hexo 就不會去 render 他了

疑難雜症

在改主題原始碼的過程中,遇到各種奇怪問題時,記得先 hexo clean 一下

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×