接續上一講專案的基礎建立後,我們已經能用基本的 Markdown 透過 Astro Layout 及其本身對 Markdown 格式的轉譯,產生出一篇 HTML 格式的頁面了。
然而若是我們想要加入更多型態的內容在文章中,例如程式碼、數學式,應該怎麼設定?甚至還要寫點互動式的內容,除了透過 .astro
的模板,能夠更統一的用 Markdown 的形式來撰文嗎?這講就來聊聊怎麼達成這些目標。
倘若我們想要保有彈性,但又不想用「類 HTML」的 Tag 語法(也就是 .astro
)來做,那就可以試試看 MDX 這種格式。
所謂的 MDX,基本上就是在 Markdown 的架構底下,同時也能插入 JSX
的語法(一種在 JavaScript 中寫 XML/HTML Markup 的語法擴充)。
在使用之前,我們一樣需要透過 npm install @astrojs/mdx
安裝 Astro 的 MDX 套件。並且在 astro.config.ts
中加入以下內容:
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import mdx from '@astrojs/mdx'; // Added
export default defineConfig({
integrations: [react(), mdx()], // Updated
});
如此一來就可以開始撰寫 MDX 的文章了。新增 src/pages/posts/third-post.mdx
的檔案。
還記得我們上一講剛剛建立過稱作 Greeting
的 Astro Component 對吧?這樣的 Component 可以直接整合進 MDX 的文章中:
---
layout: ../../layouts/BlogPostLayout.astro
title: '第三篇部落格貼文'
publishedTime: '2025-05-08 23:12:00'
updatedTime: '2025-05-08 23:12:00'
---
import Greeting from '../../components/Greeting.astro';
# The Third Blog Post
<Greeting name="John" />
MDX 是在最上方也保有 Frontmatter 記錄一些文章的基礎資訊,例如標題、新增及更新時間等等,也一樣可以透過 layout
裡面指定我們寫好的 BlogPostLayout 路徑即可,和 Markdown 到目前為止一模一樣。
額外增加的是正文中的部分,我們在 MDX 中可以使用 JavaScript 的語法了,例如 import
指令,以及直接使用 <Greeting />
的 Component。
除了基本的標題、段落文字,還有我們在 MDX 能插入的 JavaScript、寫好的 Astro / React 元件之外,也來簡單介紹一下 Astro,或是大多數的 Markdown 轉換器能夠將怎麼樣的內容轉換成 HTML。
以下是 Markdown 元素和 HTML 元素的轉換對應表
名稱 | Markdown 範例 | 轉成的 HTML |
---|---|---|
標題 | # Title , ## Title , … |
<h1>Title</h1> , <h2>Title</h2> , … |
段落 | (透過空白行分隔段落) | <p>...</p> |
換行 | (行尾兩格空白換行) | <br> |
斜體 | _italic_ |
<em>italic</em> |
粗體 | **bold** |
<strong>bold</strong> |
行內程式碼 | `int i = 0;` | <code>int i = 0;</code> |
程式碼 | ```console.log('hello');``` | <pre><code>console.log('hello');</code></pre> |
引用區塊 | > quote |
<blockquote><p>quote</p></blockquote> |
無序列表 | - item / * item |
<ul><li>item</li></ul> |
有序列表 | 1. item |
<ol><li>item</li></ol> |
分隔線 | --- |
<hr> |
連結 | [link](https//md.com) |
<a href="https://md.com">link</a> |
圖片 |  |
<img src="img.png" alt="alt"> |
其餘還有一些常見的擴充,例如刪節線、表格、待辦清單等等,GitHub 將這些擴充打包並定義了 GFM(GitHub Flavored Markdown),也就是 GitHub 的網頁中能直接呈現的 Markdown 元素。
如果要在 Astro 當中使用與 GitHub 一樣的擴充,可以透過 npm install remark-gfm
並且在 astro.config.ts
裡面加入設定。
import remarkGfm from 'remark-gfm'; // Added
export default defineConfig({
integrations: [mdx(remarkGfm)], // Updated
});
有了基本的文章元素後,身為工程師,寫點數學式子也是人之常情吧!但大多數的 Markdown 轉換器都不會原生支援,因為相比於單純的文章,在撰寫數學式上需要的是完全的另一套複雜系統。
通常在一些專業的學術刊物上,會使用 LaTeX 作為排版和產生數學式子等內容的系統。想在網頁上渲染 LaTeX 的數學式,則有常見的兩種 Libraries 來做選擇:KaTeX 或是 MathJax。
LaTeX 是一種基於 TeX 的排版系統,也是一種 Markup Language,前者由 2013 年圖靈獎得主 Leslie Lamport 所開發,而後者則是由著名「電腦程式設計藝術」的作者高德納所發明。LaTex 使用 TeX 作為其格式化引擎,可以讓使用者沒有排版的知識也能產出專業品質的刊物。
而 KaTeX 和 MathJax 都是 JavaScript 的 Library,前者由 Khan Academy 開發、後者由美國數學學會管理,兩者主要的差異在於:
既然我的目的是以撰寫部落格為主,簡單的數學式就能滿足我大部分需求了,不需要到更專業的學術等級;那考慮就是渲染速度了,較快的 KaTeX 就成為我的首選。
選定了 KaTeX 後,接著就來整合進現有的 Astro 專案吧!首先是相關套件的安裝:npm install katex remark-math rehype-katex
。
除了本體的 katex
外,還需要 remark-math
來解析 Markdown 中的數學式子,畢竟我們大部分的情境會在 Markdown 底下撰文;而 rehype-katex
則將解析完的式子渲染成 KaTeX 所需的 HTML 結構。
安裝完畢後,再來需要修改 astro.config.ts
的內容,將 remark-math
及 rehype-katex
加入到 integration
的 mdx
下。
import remarkMath from 'remark-math'; // Added
import rehypeKatex from 'rehype-katex'; // Added
export default defineConfig({
// Updated
integrations: [mdx({ remarkPlugins: [remarkMath], rehypePlugins: [rehypeKatex] })],
}
再來可以在全域或特定的 Layout 中匯入 KaTeX 的樣式,例如在部落格的模板 BlogPostLayout.astro
中的加入 import 'katex/dist/katex.min.css';
。
最後就能快樂寫算式了,隨便挑一篇 MDX 或 Markdown 的文章,在內文中加入:
Formula 1 - $E = mc^2$
Formula 2 - $\int_0^1 x^2 dx = \frac{1}{3}$
Formula 3:
$$
\begin{array}{l r}
F = ma & \text{(1)} \\
E_k = \frac{1}{2}mv^2 & \text{(2)}
\end{array}
$$
便能顯示精美的數學式。
*KaTex 產出結果