跳到主要内容

2、mdx

mdx

目录

[toc]

.md和.mdx有什么区别吗?

.md.mdx 是两种文件扩展名,用于标识 Markdown 文件,它们之间有几个关键的区别:

.md 文件

  • 定义.md 文件是标准的 Markdown 文件,采用 Markdown 语法来格式化文本。
  • 用途:用于撰写文档、说明书、博客文章等。只能包含 Markdown 支持的文本和格式,例如标题、列表、链接等。

.mdx 文件

  • 定义.mdx 文件是 Markdown 的扩展,允许在 Markdown 文档中嵌入 JSX(通常用于 React 组件)
  • 用途:适用于需要在文档中插入 React 组件的场景,比如在文档中直接使用可重用的组件、交互式示例等

总结

  • .md:仅支持 Markdown 语法,适合文本内容。
  • .mdx:支持 Markdown 和 JSX,适合结合 React 组件的文档。

如果你在一个使用 React 或其他框架的项目中,并且需要在文档中使用组件,.mdx 是一个很好的选择,而标准的文档或博客则可以使用 .md

1、什么是mdx

image-20240508154618734

MDX 允许你在 Markdown 内容中使用 JSX。你可以导入交互式图表或警报等组件,并将它们嵌入到你的内容中。这使得使用组件编写长篇内容变得非常有趣。

image-20240508154835497

MDX 简而言之

  • ❤️ 强大的:MDX 混合了 markdown 和 JSX 语法,完美适合基于 JSX 的项目
  • 💻 一切都是一个组件:使用 MDX 中的现有组件并将其他 MDX 文件导入为组件
  • 🔧 可定制:决定为每个 markdown 构造渲染哪个组件 ({h1: MyHeading})
  • 📚 基于 Markdown:Markdown 的简单和优雅仍然存在,只有当你想要时才使用 JSX
  • 🔥 速度极快:MDX 没有运行时,所有编译都发生在构建阶段

哈哈 mdx 太棒了

本文介绍什么是 MDX 格式。它展示了如何在 MDX 中使用 ESM 中的 markdown、JSXJavaScript 表达式以及 importexport 语句。 有关如何将 MDX 集成到项目中的详细信息,请参阅 § 入门

本节摘要:

先决条件(Prerequisites)

要编写并享受MDX,您应该熟悉markdown(参见备忘单和教程获取帮助)和JavaScript(特别是JSX).

组件时代的 Markdown

MDX 允许你在 Markdown 内容中使用 JSX。你可以导入交互式图表或警报等组件,并将它们嵌入到你的内容中。这使得使用组件编写长篇内容变得非常有趣。🚀

更实际的是,MDX 可以解释为一种将 markdown 与 JSX 结合在一起的格式,如下所示:

# Hello, world!

<div className="note">
> Some notable things in a block quote!

</div>

标题和块引用是 markdown,而那些类似 HTML 的标签是 JSX。对于强调或标题等常见内容,Markdown 通常感觉比 HTML 或 JSX 更自然。JSX 是 JavaScript 的扩展,看起来像 HTML,但可以方便地使用组件(可重用的东西)

此示例在 <div> 上使用 className。那是因为它是为 React 编写的,而 React 期望类是这样的。其他框架(例如 Vue 和 Preact)期望类的定义不同,因此请注意,根据所使用的工具,JSX 的编写方式存在一些差异。

MDX 还支持 JavaScript 的其他一些功能:大括号 ({1 + 1}) 和 ESM(importexport)中的表达式。

MDX语法(MDX syntax)

注意:你不必对 @mdx-js/* 包使用此语法。或者一直使用它。如果你使用打包器集成,则可以通过文件扩展名(.mdx.md)在 MDX 和 Markdown 之间进行更改。或者,可以使用 options.format

MDX 语法将 markdown 与 JSX 结合起来。这给了我们一些类似于文学编程的东西。它还为我们提供了两种语言的奇怪组合:markdown 对空格敏感且宽容(你输入的内容可能不完全有效,但不会崩溃),而 JavaScript 对空格不敏感且不宽容(它确实会因拼写错误而崩溃)。

奇怪的是,我们非常喜欢它们的结合方式!

Markdown

https://commonmark.org/help/

image-20240507133123483

对于强调或标题等常见内容,Markdown 通常感觉比 HTML 或 JSX 更自然。Markdown 通常看起来更符合预期并且更简洁。而不是以下 HTML:

<blockquote>
<p>A blockquote with <em>some</em> emphasis.</p>
</blockquote>

你可以在 markdown (或 MDX)中编写等效内容,如下所示:

> A blockquote with *some* emphasis.

MDX 默认支持标准 Markdown (CommonMark):

# Heading (rank 1)
## Heading 2
### 3
#### 4
##### 5
###### 6

> Block quote

* Unordered

* List

1. Ordered
2. List

A paragraph, introducing a thematic break:

---

```js
some.code()
```

a [link](https://example.com), an

![image](./image.png)

, some *emphasis*,
something **strong**, and finally a little `code()`.

非标准 Markdown 功能(例如 GFM、frontmatter、数学、语法高亮)可以通过插件启用(参见 ¶ 使用插件)。

一些 Markdown 功能在 MDX 中不起作用

  • 缩进代码在 MDX 中不起作用:

        console.log(1) // this is a paragraph in MDX!

    这样做的原因是这样你可以很好地缩进你的组件:

    <main>
    <article>
    # Hello!
    </article>
    </main>
  • 自动链接在 MDX 中不起作用。原因是它们与 JSX 无法区分(例如:<svg:rect>),而我们更喜欢明确的。如果你需要链接,请使用完整链接:[descriptive text](https://and-the-link-here.com)

  • HTML 语法在 MDX 中不起作用,因为它已被 JSX(<img><img />)取代。你可以使用大括号中的 JavaScript 注释来代替 HTML 注释:{/* comment! */}

未转义的左尖括号/小于 (`<`) 和左大括号 (`{) 必须转义:`<``{`(或使用表达式:`<``{`)

有关 MDX 与 Markdown 有何不同的更多信息,请参见 记录在这里

JSX

JavaScript(特别是JSX).

https://facebook.github.io/jsx/

image-20240507132955116

JSX 是 JavaScript 的扩展,看起来像 HTML,但可以方便地使用组件(可重用的东西)。JSX 通常与 React、Preact 或 Vue 等前端框架结合使用。这些框架添加了对组件的支持,使你可以更改重复的内容,例如以下标记:

<h2>Hello, Venus!</h2>
<h2>Hello, Mars!</h2>

...到 JSX(或 MDX),如下所示:

<Welcome name="Venus" />
<Welcome name="Mars" />

JSX 适合组件。它使重复的事情变得更加清晰,并允许关注点分离。MDX 支持 JSX 语法。下面的内容看起来很像 HTML:

<h1>Heading!</h1>

<abbr title="HyperText Markup Language">HTML</abbr> is a lovely language.

<section>
And here is *markdown* in **JSX**!
</section>

但正如前面提到的,你也可以使用组件。请注意,必须定义组件。你可以导入它们、在本地定义它们或稍后传递它们(参见 § 使用 MDX):

<MyComponent id="123" />

You can also use objects with components, such as the `thisOne` component on
the `myComponents` object: <myComponents.thisOne />

<Component
open
x={1}
label={'this is a string, *not* markdown!'}
icon={<Icon />}
/>

image-20240508164030423

有一些边缘情况 MDX 与 JSX 的不同之处

表达式

MDX 还支持大括号内的 JavaScript 表达式:

Two 🍰 is: {Math.PI * 2}

表达式可以包含整个 JavaScript 程序,只要它们(封装在)计算结果为可渲染内容的表达式中即可。你可以像这样使用 IIFE



{(function () {
const guess = Math.random()

if (guess > 0.66) {
return <span style={{color: 'tomato'}}>Look at us.</span>
}

if (guess > 0.33) {
return <span style={{color: 'violet'}}>Who would have guessed?!</span>
}

return <span style={{color: 'goldenrod'}}>Not me.</span>
}

)()}

表达式可以为空或仅包含注释:

ESM

MDX 还支持 JavaScript 中的 importexport 语句。这些 ESM 功能可以在 MDX 中使用来定义事物:

import {External} from './some/place.js'

export const Local = properties => <span style={{color: 'red'}} {...properties} />

An <External>external</External> component and a <Local>local one</Local>.

ESM 也可用于非组件(数据):

import {Chart} from './chart.js'
import population from './population.js'
export const pi = 3.14

<Chart data={population} label={'Something with ' + pi} />

交织

如果文本和标签位于同一行,则可以在 JSX 中使用 markdown“内联”,但不能使用“块”:

<div># this is not a heading but *this* is emphasis
</div>

一行上的文本和标签不会生成块,因此它们也不会生成 <p>。在不同的线路上,他们这样做:

<div>
This is a `p`.

</div>

我们使用这个规则来区分(同一条线或不同线)。不基于 HTML 中元素的语义。所以你可以构建不正确的 HTML(你不应该这样做):

<h1 className="main">
Don’t do this: it’s a `p` in an `h1`
</h1>

<h1 className="main">Do this: an `h1` with `code`</h1>

如果文本和标签位于同一行,但相应的标签位于不同行,则无法换行“块”:

Welcome! <a href="about.html">

This is home of...

# The Falcons!</a>

这是因为要解析 markdown,我们首先必须将其分为“块”。所以在这种情况下有两个段落和一个标题。在第一段中留下一个开始 a 标签,并在标题中留下一个杂散的结束 a 标签。

进一步阅读

2、入门

3、使用mdx

大多数打包器、框架和编辑器都有集成。无论你是使用 Docusaurus、Next.js 还是 Vite 进行构建。你更喜欢 **Rollup、esbuild 或 webpack。**你正在使用 React、Preact 或 Vue开始使用 »

4、扩展mdx

5、mdx故障排错

FAQ

范例

你可以打开下面两篇文章观察下:

发现两个作者在讲解知识的时候,都配有大量的生动案例,通过一系列的鼠标或键盘操作来和读者的教程进行互动。来达到读者在观察网页上一些元素的样式和行为发生的变化过程中思考背后的原理的目的。

很重要的一点:我们已经从单纯被动接受信息,到一种参与互动,仿佛在跟着文章思维和作者进行交流。这种学习的过程更加立体和深刻。

另外通过这种方式写作,更能锻炼写作者对某个知识点背后的原理和在实际场景中的应用的深入理解。因为每个案例都是该知识点在实际应用中的一种折射。

我理解这种创作的深度比单纯的码文字和贴图要高的多。

而之所以有这种变化的趋势,我觉得背后得益于 Web 技术的发展的助推,静态网站生成技术对 mdx 格式的文件的支持:同一个文件中不仅支持 md 语法,还能直接写 jsx 代码在文件中执行。

https://mdxjs.com

让 Markdown 步入组件时代 MDX 将 markdown 和 JSX 语法完美地融合在一起,完美地适配 基于 JSX 的项目,亦可将现有的组件使用到 MDX 中,并且可以将其它 MDX 文件作为组件导入。 保留了 markdown 的简洁和优雅, 你只需在需要时使用 JSX。

我们知道有这种变化之后,不妨继续探索下,可以从哪些方面去实践?

首先我们从交互形式的角度分析:

  • 鼠标点击操作触发
  • 通过键盘按键
  • 鼠标滚轮滚动
  • 眼球互动(VR 场景)
  • 手指操作(VR 场景)

下面我们来通过几个真实的案例,具体看看都有哪些可能性?

通过键盘按键互动

这是一种常见的应用场景,通过监听键盘大小键的关闭和开启来给与用户输入密码时友好提示,避免大小写切换时用户感知上的迷惑。

核心代码如下 👇:

window.addEventListener('keydown', detectCapsLock)
window.addEventListener('keyup', detectCapsLock)

function detectCapsLock(e) {
if (e.getModifierState('CapsLock')) {
// caps lock is on
} else {
// caps lock is off
}
}

我们可以通过这种真实场景的模拟,来感受下隐藏在背后的技术的实现过程,比单纯的代码和文字讲解要更生动,更能激发人的探索欲。

及时编码,实时展示效果

这是一段代码块的 live 模式,依赖于开源库 https://github.com/FormidableLabs/react-live 实现。使得可以同时通过可编辑的源代码实时预览两种模式来渲染 React 组件。

修改代码块中防抖函数中的数值来观察结果区文字变化的响应速度

实时编辑器

function App() {
const [mouseX, setMouseX] = React.useState(null);
const [mouseY, setMouseY] = React.useState(null);

const handleMouseMove = React.useMemo(
() => debounce((ev) => {
setMouseX(ev.clientX);
setMouseY(ev.clientY);
}, 250), // 修改防抖数值观察变化
[]
);

return (
<div
style={{ padding: '40px 20px', border: '2px dashed #ebedf0' }}
onMouseMove={handleMouseMove}>
鼠标位置:{ mouseX ? `X: ${mouseX}` : '' } { mouseY ? `Y: ${mouseY}` : '' }
</div>
);
}

结果

Loading...

一边写代码,一边展示效果,有点类似本地的网页开发体验。

这种及时显示代码效果的的互动形式,大大提高了读者对代码的兴趣。

相比在文章中附上 CODEPEN(https://codepen.io) 这种代码演示平台的链接。避免了阅读时文章和代码试验区的切换的割裂感,完美与正文集成在一起, 既保证了顺畅的阅读体验,还能让我们体验在线调试代码的过程。

通过改变配置,改变页面效果

在学习 Flex 布局时,相比单纯介绍各个属性的含义和用法。如果通过这样一个真实的案例:更改下面盒子的宽度,观察表单的布局和样式的变化:

先通过案例让你产生兴趣,顺便思考背后的技术的实现。然后再点开查看代码,这样的教程是不是更有意思?

需求

需求1:如何把docusaurus页面也渲染成如下mdx-editor的渲染效果呢?

docusaurus里该如何配置呢?

image-20240508073030123

默认docsuaurus效果还是太单调了……

image-20240508075142340

需求2:typora里能否使用mdx来渲染自己页面呢?

可以利用mdx对typora的css进行皮肤定制吗?

MDX 是一种将 Markdown 和 JSX 结合的格式,允许在 Markdown 文档中嵌入 React 组件。然而,MDX 本身并不直接关联到 Typora 这样的 Markdown 编辑器,而是更多地用于静态网站生成器(如 Docusaurus、Gatsby 等)中。

Typora 是一个所见即所得的 Markdown 编辑器,它允许用户通过自定义 CSS 来改变文档的外观。如果你想要定制 Typora 的皮肤,你可以通过以下步骤进行:

  1. 打开 Typora 的偏好设置: 在 Typora 中,点击菜单栏的 文件 > 偏好设置

  2. 进入外观设置: 在偏好设置中,选择 外观 标签页。

  3. 编辑主题文件: 在 外观 标签页中,你可以看到 打开主题文件夹 的选项。点击这个选项,Typora 会打开一个文件夹,里面包含了当前使用的主题的 CSS 文件。

  4. 编辑 CSS 文件: 你可以编辑这些 CSS 文件来改变 Typora 的外观。例如,你可以改变标题的颜色、字体、背景等。

  5. 保存并应用更改: 编辑完成后,保存 CSS 文件,并重启 Typora 以应用新的样式。

请注意,Typora 的 CSS 定制仅限于 Typora 编辑器本身,并不会影响使用 MDX 格式生成的静态网站。如果你想要定制使用 MDX 生成的静态网站的样式,你需要编辑网站的 CSS 文件,这通常是在你的静态网站生成器项目的 src/csssrc/theme 目录下。

例如,在 Docusaurus 项目中,你可以通过编辑 src/css/custom.css 文件来定制网站的样式。在这个文件中,你可以添加自定义的 CSS 规则来改变网站的外观。

总结来说,MDX 和 Typora 的 CSS 定制是两个不同的领域,MDX 用于静态网站的内容生成,而 Typora 的 CSS 定制用于编辑器的外观。两者可以通过各自的 CSS 文件进行定制,但它们之间没有直接的联系。

mdx文档

mdx中文官网

https://mdx.nodejs.cn/

mdx官网

https://mdxjs.com/

mdx游乐场

https://mdxjs.com/playground/

mdx文档

https://mdxjs.com/docs/

markdown的组件时代。

mdx3

新:MDX 3!

这次是小版本,没什么大更新,有时候也不错!这主要是放弃了对旧 Node 的支持(使用 16 或更高版本),在 MDX 中添加现代 ES2024 支持,在 MDX 中支持 await(如果你的框架也支持),并删除了几个已弃用的选项。

https://blog.csdn.net/lecepin/article/details/136016869

mdx playground

https://mdx.nodejs.cn/playground/

image-20240508155027358

npm install @mdx-js/mdx @mdx-js/react

image-20240508071546178

gpt:如何在docusaurus里安装mdx?

在 Docusaurus 2 中,MDX 是默认支持的,因此你不需要单独安装 MDX。Docusaurus 2 使用了一个名为 @mdx-js/react 的库来支持在 Markdown 文件中嵌入 React 组件。

如果你使用的是 Docusaurus 2,你只需要按照以下步骤创建和编写你的 MDX 文件:

  1. 创建一个新的页面: 在 src 目录下创建一个新的 .mdx 文件,例如 src/pages/my-page.mdx

  2. 编写 MDX 内容: 在 my-page.mdx 文件中,你可以编写 Markdown 内容,并且可以嵌入 React 组件。例如:

    # My Page

    This is a paragraph with **bold text**.

    Here's a React component:

    ```jsx live
    function MyComponent() {
    return <h1>Hello, MDX!</h1>;
    }
  3. 运行 Docusaurus: 确保你的 Docusaurus 项目已经安装并配置好。然后运行以下命令来启动开发服务器:

    npm start
  4. 访问页面: 打开浏览器并访问 http://localhost:3000/my-page,你应该能看到你刚刚创建的页面。

如果你使用的是 Docusaurus 1,那么 MDX 的支持需要通过安装 @mdx-js/mdx@mdx-js/react 来实现。以下是安装步骤:

  1. 安装依赖: 在你的 Docusaurus 1 项目中,运行以下命令来安装 MDX 相关的依赖:

    npm install @mdx-js/mdx @mdx-js/react
  2. 配置 MDX: 在 siteConfig.js 文件中,确保 presets 数组中的 docsblog 配置项包含了 useMDXComponents 选项,例如:

    module.exports = {
    // ...
    presets: [
    [
    '@docusaurus/preset-classic',
    {
    docs: {
    // ...
    useMDXComponents: {
    // 这里可以自定义 MDX 组件
    },
    },
    // ...
    },
    ],
    ],
    // ...
    };
  3. 创建和编写 MDX 文件: 与 Docusaurus 2 类似,在 docsblog 目录下创建 .mdx 文件,并编写内容。

  4. 运行 Docusaurus: 运行以下命令来启动开发服务器:

    npm run start
  5. 访问页面: 访问你的 MDX 页面,你应该能看到嵌入的 React 组件正常工作。

请注意,Docusaurus 1 已经不再维护,建议升级到 Docusaurus 2 以获得更好的支持和功能。

自己测试效果:

image-20240508072313329

gpt:docusauru如何自定义mdx配置?

在 Docusaurus 中自定义 MDX 配置可以通过编辑 MDX 加载器的设置来实现。Docusaurus 使用 @docusaurus/mdx-loader 来处理 MDX 文件,并集成了一些默认的配置。如果你想要添加自定义配置,比如自定义组件、插件等,你需要在项目的配置文件中进行适当的更改。

以下是如何在 Docusaurus 2 中自定义 MDX 配置的步骤:

1. 安装额外的 MDX 插件(如果需要)

首先,如果你需要添加额外的 MDX 插件,比如 remark-imagesrehype-katex,你需要先将它们安装到你的项目中:

npm install remark-images rehype-katex

2. 修改 docusaurus.config.js

在项目的根目录找到 docusaurus.config.js 文件,并修改其中的配置来包含你的自定义 MDX 配置。主要是在 presets 配置项中,特别是 @docusaurus/preset-classic 的部分,你可以在 docsblog 配置中添加 remarkPluginsrehypePlugins

module.exports = {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
// Docs 特定的配置项
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/your/repo/edit/main/website/',
// 添加 MDX 插件
remarkPlugins: [require('remark-images')],
rehypePlugins: [require('rehype-katex')],
},
blog: {
// Blog 特定的配置项
showReadingTime: true,
editUrl: 'https://github.com/your/repo/edit/main/website/blog/',
// 在博客中也使用相同的插件
remarkPlugins: [require('remark-images')],
rehypePlugins: [require('rehype-katex')],
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
// ...
};

3. 重启 Docusaurus

修改配置后,你需要重启 Docusaurus 来应用这些更改:

npm run start

4. 使用自定义 MDX 组件

如果你想在你的 MDX 文件中使用自定义 React 组件,你可以简单地在 MDX 文件中导入它们,并像使用常规 React 组件一样使用:

import MyCustomComponent from '../src/components/MyCustomComponent';

# Hello from MDX

This is a paragraph. And below is a custom component:

<MyCustomComponent />

通过这种方式,你可以充分利用 MDX 在 Markdown 中嵌入 React 组件的能力,增强你的文档或博客文章的互动性和功能性。

小结

以上步骤展示了如何在 Docusaurus 中自定义 MDX 配置,包括添加额外的处理插件和使用自定义组件。这样可以使你的文档更加丰富和多功能。

mdx应用

docusaurus由mdx驱动

image-20240507131835831

在markdown中写JSX

image-20240508044051257

image-20240508044058914

b站

https://www.bilibili.com/video/BV1PS4y167Rd/?spm_id_from=333.337.search-card.all.click&vd_source=77325423ced14ef15b0723db235167e3

image-20240508073435520

image-20240508073502944

测试效果

范例

image-20240508073702878

渲染后效果:

image-20240508073728916

范例:button组件

image-20240508074231203

image-20240508074259513

image-20240508074321126

范例

image-20240508074701819

自定义组件列表

相当于markdown的换肤功能!只是一个基础能力。(其实不用mdx也是可以做到的)

mdx最强大一点是:可以让我们在markdown里直接用jsx来写组件。(react/vue)

image-20240508073816492