--- title: "透過 GitHub Actions 更新筆記內容 | Update note with GitHub Actions" description: 透過 GitHub Actions 更新筆記內容. image: https://user-images.githubusercontent.com/26391143/156984539-606601e9-ad2c-48d6-a783-f6a95bf0bd44.png author: Hsins tags: HackMD-Theme, HackMD-API --- {%hackmd @themes/notion %} <div style="text-align:center;"> ![](https://user-images.githubusercontent.com/26391143/156984539-606601e9-ad2c-48d6-a783-f6a95bf0bd44.png =150x) # 透過 GitHub Actions 更新筆記內容 </div> > **使用範例**:透過 GitHub Actions 更新筆記內容 > **提案人員**:[@Hsins (H.-H. Peng)](https://hackmd.io/@Hsins) > **聯絡方式**:[hsinspeng@gmail.com](hsinspeng@gmail.com) > **專案倉庫**:[Hsins/hackmd-themes](https://github.com/Hsins/hackmd-themes) <details> <summary>目錄(🔎 點擊展開)</summary> [toc] </details> ## 範例說明 ### 自訂主題 [HackMD](https://hackmd.io/) 允許使用者在文件中添加如下的 [**內部樣式表**](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style) 來變更文件樣式: ``` html <style> p { color: #26b72b; } </style> ``` 並且可以透過如下的語法在其他文件中嵌入既有文件: - **固定連結**:`{%hackmd @Hsins/theme-notion %}` - **筆記代號**:`{%hackmd apDKTl3FRzG2MMi8U2L4Mw %}` 因此使用者可以透過在一份文件中定義好樣式主題後,在其他文件中透過文件標識碼 `noteId` 或自訂的永久連結來套用樣式主題。 ### 壓縮體積 在 Yahoo! 開發者團隊多年前的文章 [Best Practices for Speeding Up Your Web Site](https://developer.yahoo.com/performance/rules.html) 中曾提到: ==_Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times._== 由於 HackMD 添加樣式的方式是透過嵌入他篇文章的 CSS 樣式來達成效果,我們可以利用一系列的工具來完成縮小 CSS 樣式大小的操作: - 開發者在 `*.css` 文件中實作並調整樣式,此檔案須交由版本控制軟體進行追蹤 - 提交代碼後,透過 GitHub Actions 觸發任務 1. 透過 CSS 後處理器(Postprocessors) [PostCSS](https://github.com/postcss/postcss) 處理瀏覽器兼容問題並最小化體積 2. 將最小化後的 CSS 樣式填入 `*.md` 文件中 3. 同步更新對應 `noteId` 的文件 ## 實作說明 ### 目錄架構 以專案 [hackmd-themes](https://github.com/Hsins/hackmd-themes) 為例,其目錄架構如下所示: ``` . ├── .github │ └── workflows │ ├── update-themes.yaml │ └── ... ├── commands │ ├── update.js │ └── utils.js ├── styles │ └── [theme-slug].css ├── themes │ └── [theme-slug].md ├── configs.js ├── package.json ├── postcss.config.cjs └── ... ``` - `./.github/workflows/update-themes.yaml` 定義了 GitHub Actions 工作流的觸發事件與具體行為 - `./commands` 存放相關的腳本程式 - `./styles` 存放 `[theme-slug].css` 檔案,主要開發更動都在此處 - `./themes` 存放 `[theme-slug].md` 檔案,會根據設定檔案由 GitHub Actions 執行腳本生成 - `./configs.js` 中存放設定檔案 ### 內容設定 設定檔案 `./configs.js` 中存放了 API 設定、路徑設定與主題資訊,其中主題資訊定義結構如下: ``` javascript // configs.js export const themes = [ { slug: 'theme-notion', noteId: 'apDKTl3FRzG2MMi8U2L4Mw', styleFile: 'notion.css', themeFile: 'notion.md', metadata: { name: 'HackMD Theme - Notion', description: 'Use `{%hackmd @Hsins/theme-notion %}` syntax to include this theme.', tags: ['HackMD-Theme'], }, } // ... ]; ``` 其中 `noteId` 為筆記代號,可以透過 [User Notes API](https://hackmd.io/@hackmd-api/user-notes-api) 獲取,或是從筆記頁面的網址後綴取得。 > 此處也可以添加一個命令 `yarn create`,透過 HackMD API 創建筆記後,將返回的文章編號填入設定檔中,以供後續開發使用。 ### 核心程式 由於作為樣式主題的 HackMD 檔案所需要的內容,只會由兩部分組成: - YAML Matadata 部分 - CSS Stylesheet 部分 主要程式如下: ``` javascript // update.js import { getMetadata, getStyle, updateTheme, uploadTheme } from './utils.js'; import { themes } from '../configs.js'; themes.forEach((theme) => { const metadata = getMetadata(theme); const style = getStyle(theme); const content = metadata + '\n' + style; updateTheme(theme, content); uploadTheme(theme, content); }); ``` 其中 `uploadTheme()` 使用 [`axios`](https://github.com/axios/axios) 函數庫與 HackMD API 交互,透過指定的 `noteId` 更新內容: ``` javascript // utils.js import log from 'log-beautify'; import axios from 'axios'; import { HACKMD_API_URL, HACKMD_API_TOKEN } from '../configs.js'; const uploadTheme = (theme, content) => { const axiosConfig = { method: 'patch', url: `${HACKMD_API_URL}/notes/${theme.noteId}`, headers: { 'Authorization': HACKMD_API_TOKEN, 'Content-Type': 'application/json', }, data: JSON.stringify({ content }), }; axios(axiosConfig) .then((response) => log.success(`Theme upload: ${theme.slug}.`)) .catch((error) => log.error(error)); }; ``` ### 環境變數 由於 API Token 屬於私密訊息,應妥善保存且不以明碼方式存放於程式中,此處可以針對專案倉庫創建一個 [環境(Environment)](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment) 並將 Token 存放於其 [加密機密(Encrypted secrets)](https://docs.github.com/en/actions/security-guides/encrypted-secrets) 中: <div style="text-align:center;"> ![](https://i.imgur.com/GQe7dPN.png) </div> 在 [`update-themes.yaml`](https://github.com/Hsins/hackmd-themes/blob/main/.github/workflows/update-themes.yaml) 設定中,需要指定環境以及使用的環境變數: ``` yaml=8 jobs: update-themes: # 指定環境 environment: CI runs-on: ubuntu-latest ``` ``` yaml=27 - name: Update themes and upload to HackMD run: yarn update env: # 設定環境變數 HACKMD_API_TOKEN: ${{ secrets.HACKMD_API_TOKEN }} ``` ## 後記 希望可以在目前的 HackMD API 基礎上,添加以下功能: - 更新筆記固定連結 - 使用範本創建筆記 ## 參考資料 - [HackMD API Documentation](https://hackmd.io/@hackmd-api/developer-portal) - [GitHub Actions Documentation](https://docs.github.com/en/actions) - [Best Practices for Speeding Up Your Web Site | Yahoo! Developer](https://developer.yahoo.com/performance/rules.html) - [在筆記中嵌入另一篇筆記 | HackMD 使用教學](https://hackmd.io/c/tutorials-tw/%2Fs%2Fhow-to-embed-note-tw) - [嵌入另一篇筆記,自訂背景主題 | HackMD 使用教學](https://hackmd.io/c/tutorials-tw/%2Fs%2FoaYqEJsHR3m4IwBqEeu2Mg) - [用固定網址發布筆記 | HackMD 使用教學](https://hackmd.io/c/tutorials-tw/%2Fs%2Fhow-to-share-note-tw) <!-- Widgets: License --> {%hackmd @Hsins/widget-license %} <!-- Widgets: Likecoin --> {%hackmd @Hsins/widget-likecoin %}