eallion

大大的小蜗牛

机会总是垂青于有准备的人!
mastodon
github
twitter
steam
telegram
keybase
email

在 Hugo 中使用 Shiki

除了 Hugo 在其他靜態博客如 Hexo 中都可以使用此方法。

官方簡介#

Shiki(式,一個日語詞彙,意為 “樣式”) 是一款美觀而強大的代碼語法高亮器,它與 VS Code 的語法高亮引擎一樣,基於 TextMate 的語法及主題。Shiki 能為幾乎所有主流編程語言提供非常準確且快速的語法高亮。

你不需要維護自定義的正則表達式,不需要維護自定義的 CSS,也不需要維護自定義的 HTML;因為你在 VS Code 中使用的顏色主題一樣可以用在 Shiki 上。

優勢#

只需幾分鐘即可在 Hugo 配置好 Shiki 代碼語法高亮器。

我最喜歡它的一點是,它不像其他代碼語法高亮器需要引入體積龐大的 JS 資源,Shiki 是寫入 HTML 文件的,是純靜態的。Hugo 博客項目可以利用 @shikijs/rehype 插件實現 Shiki 代碼語法高亮,在本地或 GitHub Actions 等構建平台都能輕鬆部署交付。

安裝 Shiki#

進入到 Hugo 博客的項目目錄,安裝:

前提是需要安裝 Node.jsYarn 。選擇 Yarn 是它的 GitHub Actions 緩存友好。

# cd my-hugo-project

npm install shiki
npm install @shikijs/rehype
npm install rehype-cli

配置 Hugo#

在 Hugo 的 config 中必須將 codeFences 設置為:false

[markup]
  [markup.highlight]
    codeFences = false

創建 .rehyperc#

在 Hugo 目錄中創建 .rehyperc 文件,我的配置內容如下:

{
  "plugins": [
    [
      "@shikijs/rehype",
      {
        "themes": {
          "light": "github-light",
          "dark": "github-dark-dimmed"
        }
      }
    ]
  ]
}

Rehype 有很多 插件 ,但我只配置了高亮主題,light 模式用的是 github-lightdark 模式用的是 github-dark-dimmed ,GitHub 的主題永遠值得相信。

主題列表在這裡: https://shiki.tmrs.site/themes

讓暗黑模式生效,可能需要在原來的 Hugo 的 CSS 中適配一下,比如我的博客用的是 <html class="dark"> 的方式來切換暗黑主題的,只需要在 custom.css 中加入主題顏色變量即可:

html.dark .shiki,
html.dark .shiki span {
    color: var(--shiki-dark) !important;
    background-color: var(--shiki-dark-bg) !important;
    /* 可選,用於定義字體樣式 */
    /* font-style: var(--shiki-dark-font-style) !important; */
    /* font-weight: var(--shiki-dark-font-weight) !important; */
    /* text-decoration: var(--shiki-dark-text-decoration) !important; */
}

如果是用 prefers-color-scheme: dark 的方式切換暗黑模式,簡單適配一下這幾個變量即可:

.shiki,
.shiki span {
    color: var(--shiki-dark) !important;
    background-color: var(--shiki-dark-bg) !important;
    /* 可選,用於定義字體樣式 */
    /* font-style: var(--shiki-dark-font-style) !important; */
    /* font-weight: var(--shiki-dark-font-weight) !important; */
    /* text-decoration: var(--shiki-dark-text-decoration) !important; */
}

生成 Shiki#

先運行 hugo 命令構建 Hugo,假設構建產物在 public/ 目錄,再用 rehype-cli 生成 Shiki :

# cd my-hugo-project

npx rehype-cli public -o

運行此命令可能會導致內存報錯:

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

需要限制一下內存使用:

export NODE_OPTIONS="--max_old_space_size=7168"

7168 ≈ 7G,可以根據自己的電腦配置調整,但 GitHub Actions 免費 Runner 最高是 7G

在 GitHub Actions 中使用 Shiki#

在 Hugo 目錄 package.jsonscripts 中加入:

  "scripts": {
    "shiki": "npx rehype-cli public -o"
  },

GitHub Actions Workflow:

name: Build Hugo and Deploy With Shiki

on:
  workflow_dispatch:

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
          fetch-depth: 0

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Build Hugo
        run: |
          hugo -gc --minify

      - name: Setup Node LTS
        uses: actions/setup-node@v4
        with:
          node-version: 20.x
          cache: yarn

      - name: Install and run Shiki
        run: |
          export NODE_OPTIONS="--max_old_space_size=7168"
          yarn install
          yarn run shiki || true
          # 或 👇
          # npx rehype-cli public -o --silent || true

      - name: Keep going
        # 後續流程

為了預防 Shiki 報錯而中斷 Hugo 部署流程,可以加入 || true,即使出錯也會繼續執行部署流程。常見的報錯是以前的博文可能使用了不支持的代碼名稱。

在 Cloudflare Pages 暫時還不能配置內存限制,可以使用 cloudflare/wrangler-action 這個 Actions:

      - name: Publish to Cloudflare Pages
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          quiet: true
          command: pages deploy public --project-name=${{ secrets.CLOUDFLARE_PROJECT_NAME }} --commit-dirty=true
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。