TIL (today I learned) 是一個新系列,隨手寫今天學到了什麼,今天的內容是設定 Hugo 開發環境。
最近在 Blowfish 主題發了多個 PR,發現程式碼什麼格式都有:
- indent size 0, 1, 2, 3, 4 格都有
- 有些有 semicolon 有些沒有
- 完全沒有 markdownlint
光是這些問題就很難讀程式碼了,還有 go template 導致 VS Code 無法 syntax highlight 也無法判斷 if-else/with-else 範圍,開發起來極度痛苦,所以搞了一下設定,並且流水帳做記錄。
設定 markdown 語法檢查和 editorconfig,editorconfig 用途是告訴編輯器怎麼處理該語言的文件,以 VS Code 為例,要安裝插件
格式化 markdown 時,如果想使用 cli 執行,可以安裝 markdownlint-cli2
1
| pnpm add -D markdownlint-cli2
|
cli2 和原版的差異基本上是功能和設定完全相同,加上一些額外指令和更方便的語法,並且速度更快。安裝完成後也要寫設定檔否則預設規則太嚴格,本部落格的好處就是不廢話,直接給你我調整好的設定檔,在根目錄建立 .markdownlint-cli2.yaml
:
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
| # 規則請見文檔
# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
# https://github.com/DavidAnson/markdownlint/tree/main/doc
globs:
- "**.md"
gitignore: true
ignores:
- node_modules
- themes
- .vscode
config:
MD002: false # First header should be a h1 header
MD003: false # heading-style Heading style, conflict with mermaid shortcode
MD013: false # line length
MD024: # multiple headers with the same content
siblings_only: true
MD025: false # multiple top level headers
MD026: false # trailing punctuation in header
MD028: false # blank line inside blockquote
MD029: false # ordered list item prefix
MD033: false # inline HTML
MD034: false # bare URL used
MD036: false # emphasis used instead of a header
MD041: false # first line in file should be a top level header
MD046: false # Code block style
MD049: # emphasis style
style: asterisk
MD050: # strong style
style: asterisk
|
最後再加上 .editorconfig
讓 VS Code 知道如何格式化:
1
2
3
4
5
6
7
8
9
10
| [*]
charset = utf-8
indent_size = 2
indent_style = space
[*.{sh,js,ts,css,json,yaml,toml,html}]
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
|
一般用戶的設定比較簡單,三個步驟就完成了,值得注意的是 indent_style 可以設定 tab
或是 space
,我以往都用 space,最近覺得 tab 好像也不錯,不需修改檔案就可以控制顯示的 indent 距離。
開發者就要超多工具,使用以下指令安裝
1
| pnpm add -D husky lint-staged @biomejs/biome markdownlint-cli2 prettier prettier-plugin-go-template @awmottaz/prettier-plugin-void-html
|
每個工具的任務如下:
- husky 負責 pre-commit hook,在每次提交自動執行任務
- lint-staged 負責設定任務
- biome 負責檢查 js/ts,prettier 負責 format HTML,markdownlint-cli2 負責 markdown 文件
- prettier 以及其餘 prettier 插件
要分成這樣的原因是 prettier 可以使用 override 讓他以 go-template 語法辨識 HTML 文件,否則完全無法格式化,這也是 Hugo 官方的使用方式;biome 雖然可以 lint+format 但是我懶的研究怎麼在 biome 裡面做到一樣的事情;不使用 prettier format markdown 的原因是他無法判讀 shortcode 會打亂文件,而且 markdownlint 的規則非常淺顯易懂且貼近實務。
最後還有開發者用的擴充功能:
接下來啟動 husky pnpm husky init
,然後把自動建立的 .husky/pre-commit
內容改為 pnpm exec lint-staged
,再到 package.json
設定 lint-staged 的任務:
1
2
3
4
5
6
7
8
9
| "lint-staged": {
"**/*": [
"prettier --write --list-different",
"pnpm biome lint --write --no-errors-on-unmatched"
],
"content/*.md": [
"markdownlint-cli2 --fix '#node_modules' '#themes'"
]
},
|
請注意這裡不要使用 .
,這會導致不是 staged 的文件也被 format,要 format 全部文件就在指令最後加上 "." 即可,例如 prettier --write --list-different .
。
剩下的工具就沒什麼好說的,不廢話上全套設定
.prettierrc
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
| {
"singleQuote": false,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"trailingComma": "all",
"proseWrap": "always",
"plugins": [
"prettier-plugin-go-template",
"@awmottaz/prettier-plugin-void-html"
],
"overrides": [
{
"files": ["*.html"],
"options": {
"useTabs": false,
"parser": "go-template",
"goTemplateBracketSpacing": true,
"printWidth": 112,
"bracketSameLine": true
}
},
{
"files": ["*.js", "*.mjs", "*.mts", "*.ts"],
"options": {
"semi": true,
"useTabs": false,
"printWidth": 112,
"singleQuote": false
}
},
{
"files": ["*.yml", "*.yaml"],
"options": {
"singleQuote": false
}
},
{
"files": ["*.json*"],
"options": {
"trailingComma": "none"
}
}
]
}
|
.prettierignore
# https://github.com/gohugoio/hugo/blob/b39b24962350090122b5f3927456dde710cffb57/docs/.prettierignore
# https://github.com/gohugoio/hugo/blob/b39b24962350090122b5f3927456dde710cffb57/docs/.prettierrc
# IDE
.markdownlint-cli2.yaml
# js
node_modules
package.json
pnpm-lock.yaml
pnpm-workspace.yaml
# Hugo
assets/lib
assets/css/compiled
content
themes
public
static
*.md
# invalid node
layouts/_default/_markup/_render-heading.html
layouts/partials/article-link/card.html
layouts/partials/article-link/simple.html
layouts/partials/custom/tag-and-category.html
layouts/partials/hero/custom-background-hero.html
assets/js/appearance.js
biome.json
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| {
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"files": {
"ignoreUnknown": true,
"ignore": [
"assets/lib",
"assets/js/code.js",
"themes",
"public",
"node_modules/*",
"static",
".vscode",
"*.svg"
]
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"ignore": ["themes/*"],
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 112,
"lineEnding": "lf"
},
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noForEach": "off"
}
}
},
"javascript": {
"formatter": {
"arrowParentheses": "always",
"bracketSameLine": false,
"bracketSpacing": true,
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"quoteStyle": "double",
"semicolons": "asNeeded",
"trailingCommas": "all"
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
},
"css": {
"formatter": {
"enabled": true
}
}
}
|
文章寫起來閱讀時間不用五分鐘,完成正確設定前後耗時一週。