跳至主內容
版本:3.5.2

MDX 外掛

有時候,您可能想擴充或微調您的 Markdown 語法。例如

  • 我如何使用圖片語法 (![](https://youtu.be/yKNxeF4KMsY)) 嵌入 YouTube 影片?
  • 我如何將位於其自己獨立行的連結設定不同的樣式,例如,做成一張社群卡片?
  • 我如何讓每個頁面從版權聲明開始?

答案是:建立一個 MDX 外掛!MDX 有建置的 外掛系統,可以用於自訂將 Markdown 檔案轉換至 JSX 的方式。以下有三種常見的 MDX 外掛使用情境

  • 使用現有的 remark 外掛rehype 外掛
  • 建立 remark/rehype 外掛元件以轉換現有 MDX 語法產生的元素;
  • 建立 remark/rehype 外掛元件,把新語法引入 MDX。

玩過 MDX 播放器 的話,你應該會注意到 MDX 轉譯有兩個中間步驟:Markdown AST (MDAST) 和超文字 AST (HAST),最後才會產生 JSX 成果。MDX 外掛元件也有兩種形式

  • Remark:處理 Markdown AST。
  • Rehype:處理超文字 AST。
提示

使用外掛元件,可以對專案中最常使用的 JSX 元素使用更簡潔的語法。我們提供的 注意事項 語法也是由 Remark 外掛元件產生的,你也可以這樣做,符合自己的使用案例。

預設外掛元件

在處理 Markdown 時,Docusaurus 會注入 一些預設的 Remark 外掛元件。這些外掛元件會

  • 產生目錄;
  • 針對每個標題加入錨點連結;
  • 轉換圖片和連結到 require() 呼叫。

這些都是 Remark 外掛元件常見的用例,如果你想實做你自己的外掛元件的話,也可以當成靈感來源。

安裝外掛元件

MDX 外掛元件通常是 npm 套件,所以安裝方式和其他 npm 套件一樣,使用 npm。以 數學外掛元件 為例。

npm install --save remark-math@5 rehype-katex@6
remark-mathrehype-katex 有什麼不同?

如果你好奇 Remark 和 Rehype 的不同之處,以下是個很好的範例。remark-math 操作 Markdown AST,在此它看到 $...$ 等文字,所做的操作就是將它轉換為 JSX <span class="math math-inline">...</span>,而不會對內容進行太多處理。此舉能將數學公式的提取與其渲染相互分離,這表示你可以透過替換 Rehype 外掛程式,使用其他數學渲染程式,例如 MathJax(使用 rehype-mathjax)。

接著,rehype-katex 操作 Hypertext AST,其中所有內容都已轉換為類似的 HTML 標籤。它會遍歷所有 Math 類別的元素,並使用 KaTeX\KaTeX 來剖析並將內容渲染為實際 HTML。

警告

許多官方的 Remark/Rehype 外掛為 JavaScript 模組系統的「僅 ES 模組」,Docusaurus 支援此系統。我們建議使用「ES 模組」設定檔,以更輕鬆地匯入此類套件。

接著,匯入外掛並透過「docusaurus.config.js」中的外掛或預設值設定,將其新增至外掛選項

docusaurus.config.js
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';

export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
path: 'docs',
remarkPlugins: [remarkMath],
rehypePlugins: [rehypeKatex],
},
},
],
],
};
使用 CommonJS 設定檔?

如果您決定使用 CommonJS 設定檔,可以藉由動態匯入和非同步設定函式建構器函式,載入這些 ES 模組外掛

docusaurus.config.js
module.exports = async function createConfigAsync() {
return {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
path: 'docs',
remarkPlugins: [(await import('remark-math')).default],
rehypePlugins: [(await import('rehype-katex')).default],
},
},
],
],
};
};

設定外掛

某些外掛可設定,並接受自身的選項。此時,請使用「[外掛,外掛選項]」語法,如下所示

docusaurus.config.js
import rehypeKatex from 'rehype-katex';

export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
rehypePlugins: [
[rehypeKatex, {strict: false}],
],
},
},
],
],
};

您應該查看外掛的文件,了解其支援的選項。

建立新的 rehype/remark 外掛

如果沒有現有的套件能滿足您的自訂需求,您可以建立自己的 MDX 外掛。

備註

以下說明並非建立外掛的全面指南,只是說明如何讓外掛與 Docusaurus 一起使用的範例。請參閱 RemarkRehype 文件,深入了解其運作方式。

例如,我們製作一個外掛,拜訪每個 h2 標題,並加上 第 X 節 字首。首先,在任何地方建立您的外掛原始檔,您甚至可以將其發布為獨立的 npm 套件,並依照上述說明進行安裝。我們會將外掛放在 src/remark/section-prefix.js。remark/rehype 外掛只是接收 選項 並傳回一個執行 AST 的 轉換器 的函式。

import {visit} from 'unist-util-visit';

const plugin = (options) => {
const transformer = async (ast) => {
let number = 1;
visit(ast, 'heading', (node) => {
if (node.depth === 2 && node.children.length > 0) {
node.children.unshift({
type: 'text',
value: `Section ${number}. `,
});
number++;
}
});
};
return transformer;
};

export default plugin;

現在,您可以在 docusaurus.config.js 中匯入您的外掛,並像安裝的外掛一樣使用它!

docusaurus.config.js
import sectionPrefix from './src/remark/section-prefix';

export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
remarkPlugins: [sectionPrefix],
},
},
],
],
};
提示

轉換器 有第二個參數 vfile,如果您需要存取目前 Markdown 檔案的路徑,此參數會很有用。

const plugin = (options) => {
const transformer = async (ast, vfile) => {
ast.children.unshift({
type: 'text',
value: `The current file path is ${vfile.path}`,
});
};
return transformer;
};

例如,我們的 transformImage 外掛程式會使用這個參數,將相對的圖片參考轉換為 require() 呼叫。

備註

Docusaurus 的預設外掛程式會在自訂 remark 外掛程式之前執行,這表示圖片或連結已經透過 require() 呼叫轉換為 JSX。例如,在上面的範例中,即使所有 h2 標題現在都加上 Section X. 前綴,產生的目錄仍然相同,因為產生目錄的外掛程式是在我們的自訂外掛程式之前呼叫。如果您需要在預設外掛程式處理之前處理 MDAST,請使用 beforeDefaultRemarkPluginsbeforeDefaultRehypePlugins

docusaurus.config.js
export default {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
beforeDefaultRemarkPlugins: [sectionPrefix],
},
},
],
],
};

這樣產生的目錄也會包含 Section X. 前綴。