iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
Modern Web

手刻部落格,從設計到部署的實戰攻略系列 第 13

Astro(三):用 MDX 寫文章,顯示程式碼、數學式,搭配 JavaScript 服用

  • 分享至 

  • xImage
  •  

接續上一講專案的基礎建立後,我們已經能用基本的 Markdown 透過 Astro Layout 及其本身對 Markdown 格式的轉譯,產生出一篇 HTML 格式的頁面了。

然而若是我們想要加入更多型態的內容在文章中,例如程式碼、數學式,應該怎麼設定?甚至還要寫點互動式的內容,除了透過 .astro 的模板,能夠更統一的用 Markdown 的形式來撰文嗎?這講就來聊聊怎麼達成這些目標。

MDX

倘若我們想要保有彈性,但又不想用「類 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。

Markdown / MDX 之標準轉換內容

除了基本的標題、段落文字,還有我們在 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>
圖片 ![alt](img.png) <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 及 KaTeX vs MathJax

LaTeX 是一種基於 TeX 的排版系統,也是一種 Markup Language,前者由 2013 年圖靈獎得主 Leslie Lamport 所開發,而後者則是由著名「電腦程式設計藝術」的作者高德納所發明。LaTex 使用 TeX 作為其格式化引擎,可以讓使用者沒有排版的知識也能產出專業品質的刊物。

而 KaTeX 和 MathJax 都是 JavaScript 的 Library,前者由 Khan Academy 開發、後者由美國數學學會管理,兩者主要的差異在於:

  1. KaTeX 僅實作了 LaTeX 的部分定義,而 MathJax 支援 LaTeX 和 MathML 等 Markup Language,能顯示的數學式比 KaTeX 來得豐富
  2. 但在載入速度上,KaTeX 則明顯比 MathJax 來得更快,這是由於 KaTeX 的設計是以速度優先,而 MathJax 則更重視完整度;如果要給個體感值,KaTeX 的速度感大約是閃一下,而 MathJax 則有接近秒的感覺(0.5-1 sec)

既然我的目的是以撰寫部落格為主,簡單的數學式就能滿足我大部分需求了,不需要到更專業的學術等級;那考慮就是渲染速度了,較快的 KaTeX 就成為我的首選。

安裝 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 加入到 integrationmdx 下。

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 產出結果

*KaTex 產出結果

參考資料

  1. MDX - What is MDX
  2. React - Writing Markup with JSX
  3. GitHub Flavored Markdown Spec
  4. Wiki - LaTeX
  5. Wiki - KaTeX
  6. Wiki - TeX

上一篇
Astro(二):初始化專案,理解 Astro Components 及 Layouts 基礎
下一篇
Astro(四):淺談圖片,Baseline 及 Progressive JPEG 和 WebP、AVIF
系列文
手刻部落格,從設計到部署的實戰攻略19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言