渲染 Markdown 文件 - 自動生成和更新項目文檔

司馬遷如果使用 GitHub Actions 就可以自動更新《史記》了。
在這篇教程中,我們將探討如何使用 GitHub Actions 自動生成和更新 Markdown 文件。
我們要使用 Actions 自動從 fonts.json
文件中生成一個格式化的字體列表並更新 README.md
文件。這包括讀取 JSON 文件內容、生成 Markdown 表格,以及在 README 文件中更新這些內容。
今日範例程式:https://github.com/Edit-Mr/2024-GitHub-Actions/tree/main/20
1. 背景與目標
emfont 是一個免費的繁體中文 Web Font 服務。在之前字體列表存放在 Database/fonts.json
文件中,我們希望自動更新 README.md
文件中的字體列表。這樣可以確保文檔始終保持最新狀態,並且減少了手動更新的工作量。
emfont GitHub: https://github.com/emfont/emfont
今天我們要來復刻這個專案。首先請你準備 fonts.json
。你可以透過上面的 GitHub 連結下載。這個 JSON 文件包含了字體的詳細信息,例如名稱、風格、字種、版本、許可證和來源。以下是 JSON 文件的一部分內容:
1{
2
3 "975HazyGoSC":{
4 "name": { "zh": "975 朦胧黑体", "en": "975 Hazy Go SC" },
5 "style": "normal",
6 "weight": [200,300,400,500,600],
7 "class": "emfont-975HazyGoSC",
8 "version": "v2.01",
9 "license": "OFL-1.1",
10 "source": "https://github.com/lxgw/975HazyGo"
11 },
12 "CEFFontsCJK":{
13 "name": { "zh": "快去写作业 CJK", "en": "CEF Fonts CJK" },
14 "style": ["normal","mono"],
15 "weight": [400],
16 "class": "emfont-CEFFontsCJK",
17 "version": "v2.16",
18 "license": "OFL-1.1",
19 "source": "https://github.com/Partyb0ssishere/cef-fonts-cjk "
20 },
21 "ChenYuLuoYan":
22 {
23 "name": { "zh": "辰宇落雁體", "en": "ChenYuLuoYan Thin" },
24 "style": "normal",
25 "weight": [400],
26 "class": "emfont-ChenYuLuoYan",
27 "version": "v1.0",
28 "license": "OFL-1.1",
29 "source": "https://github.com/Chenyu-otf/chenyuluoyan_thin"
30 },
接下來我們要來準備 README.md。這個文件將會包含字體列表。我們將在 和
之間插入 Markdown 表格。
1# emfont
2
3免費的繁體中文 Web Font 服務。
4
5> 如果你喜歡這個項目,認同我們的理念,歡迎在 GitHub 給我們 ⭐ 一顆星星,分享給你的朋友,或是留下你寶貴的意見。
6
7## 字體列表
8
9
10
11
設定 GitHub Actions
我們將設定 GitHub Actions 自動更新 README.md
文件。當 Database/fonts.json
文件有變動時,工作流程會自動執行,生成新的 Markdown 表格並更新 README 文件。
步驟 1:創建 GitHub Actions 工作流程
在 .github/workflows
目錄下創建一個新的 YAML 文件,例如 update-font-list.yml
,並添加以下內容:
1name: Update Font List
2
3on:
4 push:
5 paths:
6 - "Database/fonts.json"
7 workflow_dispatch:
8
9jobs:
10 update-readme:
11 runs-on: ubuntu-latest
12
13 steps:
14 - name: Checkout repository
15 uses: actions/checkout@v3
16
17 - name: Set up Node.js
18 uses: actions/setup-node@v3
19 with:
20 node-version: "20"
21
22 - name: Update README.md
23 run: node src/workflows/update-readme.js
24
25 - name: Check for changes
26 id: git-diff
27 run: |
28 git diff --quiet || echo "::set-output name=changes::true"
29
30 - name: Commit and Push Changes
31 run: |
32 if [[ "${{ steps.git-diff.outputs.changes }}" == "true" ]]; then
33 git config --local user.email "action@github.com"
34 git config --local user.name "GitHub Actions"
35 git add .
36 git commit -m "📋 Update font list"
37 git push
38 else
39 echo "No changes to commit. Skipping push."
40 fi
這個工作流程會在 Database/fonts.json
文件發生變更時自動執行,並更新 README.md
文件中的字體列表。
今天沒有要使用第三方套件,所以不需要安裝,也不需要設定 GitHub Secrets。
步驟 2:編寫生成 Markdown 的腳本
在 src/workflows
目錄下創建 update-readme.js
文件,並添加以下內容:
1import fs from "fs";
2import path from "path";
3import { fileURLToPath } from "url";
4
5// Convert __dirname to work with ES modules
6const __filename = fileURLToPath(import.meta.url);
7const __dirname = path.dirname(__filename);
8
9const fontsFilePath = path.join(
10 __dirname,
11 "..",
12 "..",
13 "Database",
14 "fonts.json"
15);
16const readmeFilePath = path.join(__dirname, "..", "..", "README.md");
17
18// Read and parse the fonts.json file
19const fontsData = JSON.parse(fs.readFileSync(fontsFilePath, "utf8"));
20
21// Function to convert JSON data to a markdown table
22function generateMarkdownTable(data) {
23 const headers = [
24 "Font ID",
25 "中文名稱",
26 "英文名稱",
27 "字體風格",
28 "字種",
29 "Class",
30 "版本",
31 "許可證",
32 "來源"
33 ];
34 const rows = Object.entries(data).map(([id, details]) => {
35 const {
36 name,
37 style,
38 weight,
39 class: className,
40 version,
41 license,
42 source
43 } = details;
44 return [
45 id,
46 name.zh || "",
47 name.en || "",
48 style || "",
49 weight.join(", ") || "",
50 className || "",
51 version || "",
52 license || "",
53 source || ""
54 ].join(" | ");
55 });
56
57 const table = [
58 headers.join(" | "),
59 headers.map(() => "---").join(" | "),
60 ...rows
61 ].join("\n");
62
63 return table;
64}
65
66// Generate the markdown table
67const markdownTable = generateMarkdownTable(fontsData);
68
69// Read the current README.md file
70const readmeContent = fs.readFileSync(readmeFilePath, "utf8");
71
72// Update the section of the README.md file where the table should be inserted
73const updatedReadmeContent = readmeContent.replace(
74 /[\s\S]*/,
75 `\n${markdownTable}\n`
76);
77
78// Write the updated README.md file
79fs.writeFileSync(readmeFilePath, updatedReadmeContent);
80
81console.log("README.md has been updated");
腳本解析
- 讀取 JSON 文件: 腳本從
Database/fonts.json
讀取字體數據。 - 生成 Markdown 表格:
generateMarkdownTable
函數將 JSON 數據轉換為 Markdown 格式的表格。 - 更新 README 文件: 腳本讀取
README.md
文件,並將生成的 Markdown 表格插入到標記為和
之間的區域。
小結
通過今天的教程,我們探討了如何使用 GitHub Actions 自動生成和更新 Markdown 文件。我們通過編寫腳本來從 JSON 文件生成 Markdown 表格,並將其更新到 README.md
文件中。這樣的自動化流程能夠確保文檔始終保持最新狀態,並且減少了手動更新的工作量。