跳转到内容

Astro 中的 Markdown

Markdown 通常用于创作文本繁重的内容,如博客文章和文档。Astro 包括对 Markdown 文件的内置支持,这些文件还可以包括 frontmatter YAML 来定义自定义属性,例如标题、描述和标签。

在 Astro 中,你可以在 Markdown 中创作内容,然后在 .astro 组件中渲染它。它结合了为内容设计熟悉的书写格式、 Astro 组件语法以及架构的灵活性。

你的本地 Markdown 文件可以保存在 src/ 目录中的任何位置。要将单个本地的 Markdown 文件的导入到 .astro 组件,可以使用 import 语句来实现,而要想一次性查询多个文件,则可以使用 Vite 的 import.meta.glob()

如果你有一组相关的 Markdown 文件,可以考虑 将它们定义为集合。这将为你提供一些便利,其中包括了能够将 Markdown 文件存储在文件系统上的任何位置或使用远程存储。

集合还允许你使用专注于内容的优化 API 来查询和呈现你的内容。集合适用于共享相同结构的数据集,例如博客文章或产品项。当你在 schema 中定义集合时,还可以在编辑器中获得验证、类型安全和智能提示。

类 JSX 的动态表达式

段落标题 类 JSX 的动态表达式

导入或查询 Markdown 文件后,你可以在 .astro 组件中编写包含 frontmatter 数据和正文内容的动态 HTML 模板。

src/posts/great-post.md
---
title: '有史以来最好的文章'
author: 'Ben'
---
这是我的 _很棒_ 的文章!
src/pages/my-posts.astro
---
import * as greatPost from '../posts/great-post.md';
const posts = Object.values(await import.meta.glob('../posts/*.md', { eager: true }));
---
<p>{greatPost.frontmatter.title}</p>
<p>作者:{greatPost.frontmatter.author}</p>
<p>文章归档:</p>
<ul>
{posts.map(post => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
</ul>

当通过辅助函数从集合中获取数据时,Markdown 的 frontmatter 属性在 data 对象(例如 post.data.title)上可用。此外,body 包含了 Markdown 的正文内容,这部分内容是原始的、未编译的字符串类型。

请参阅完整的 集合条目类型

当使用 importimport.meta.glob() 导入 Markdown 时,以下导出的属性在你的 .astro 组件中可用:

  • file - 绝对文件路径(例如 /home/user/projects/.../file.md)。
  • url - 如果是页面,则为页面的 URL(例如 /zh-cn/guides/markdown-content)。
  • frontmatter - 包含了文件的 YAML frontmatter 中所指定的任何数据。
  • <Content /> - 返回文件完整渲染内容的组件。
  • rawContent() - 一个函数,将原始 Markdown 文档作为字符串返回。
  • compiledContent() - 一个函数,将 Markdown 文档编译为 HTML 字符串后返回。
  • getHeadings() - 一个异步函数,用于返回文件中所有标题(<h1><h6>)的数组,类型为:{ depth: number; slug: string; text: string }[]。每个标题的 slug 都对应了给定标题生成的 ID,可用于锚点链接。

示例 Markdown 博客文章可能会传递以下 Astro.props 对象:

Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** 从博客文章中获取的 Frontmatter */
title: "Astro 0.18 Release",
date: "Tuesday, July 27 2021",
author: "Matthew Phillips",
description: "Astro 0.18 is our biggest release since Astro launch.",
},
getHeadings: () => [
{"depth": 1, "text": "Astro 0.18 Release", "slug": "astro-018-release"},
{"depth": 2, "text": "Responsive partial hydration", "slug": "responsive-partial-hydration"}
/* ... */
],
rawContent: () => "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]",
compiledContent: () => "<h1>Astro 0.18 Release</h1>\n<p>A little over a month ago, the first public beta [...]</p>",
}

<Content /> 组件可通过从 Markdown 文件导入 Content 来使用。此组件返回文件的完整正文内容,并渲染为 HTML。你可以选择将 Content 重命名为你喜欢的任何组件名称。

同样,你也可以通过渲染 <Content /> 组件来 渲染 Markdown 集合条目的 HTML 内容

src/pages/content.astro
---
// 导入语句
import {Content as PromoBanner} from '../components/promoBanner.md';
// 集合查询
import { getEntry, render } from 'astro:content';
const product = await getEntry('products', 'shirt');
const { Content } = await render();
---
<h2>今日促销</h2>
<PromoBanner />
<p>促销截止至:{product.data.saleEndDate.toDateString()}</p>
<Content />

在 Markdown 中编写标题会自动为你提供锚点链接,以便你可以直接跳转到页面的某些部分。

src/pages/page-1.md
---
title: 我的文章目录
---
## 简介
当我使用 Markdown 时,我可以在同一个页面内链接到 [我的结论](#结论) 部分。
## 结论
我可以通过在浏览器访问 `https://example.com/page-1/#简介` 以直接导航到简介部分。

Astro 基于 github-slugger 生成标题 id。你可以在 github-slugger 文档 中找到更多示例。

Astro 将 id 属性注入到 Markdown 和 MDX 文件中的所有标题元素(<h1><h6>)中,并提供 getHeadings() 工具函数来检索 Markdown 导出属性 中的这些 ID。

你可以通过添加注入 id 属性的 rehype 插件(例如 rehype-slug)来自定义这些标题 ID。你的自定义 ID 将替代 Astro 的默认 ID,反映在 HTML 输出和 getHeadings() 返回的数组中。

默认情况下,Astro 会在你的 rehype 插件运行后注入 id 属性。但如果其中一个自定义 rehype 插件需要访问 Astro 注入的 ID,你可以直接导入并使用 Astro 的 rehypeHeadingIds 插件。确保在任何依赖它的插件之前添加 rehypeHeadingIds

astro.config.mjs
import { defineConfig } from 'astro/config';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import { otherPluginThatReliesOnHeadingIDs } from 'some/plugin/source';
export default defineConfig({
markdown: {
rehypePlugins: [
rehypeHeadingIds,
otherPluginThatReliesOnHeadingIDs,
],
},
});

Astro 中的 Markdown 支持由 remark 提供,remark 是一个强大的解析和处理工具,拥有一个活跃的生态系统。目前不支持其他 Markdown 解析器,如 Pandoc 和 markdown-it。

Astro 默认应用 GitHub 风格的 MarkdownSmartyPants 插件。这带来了一些便利,例如从文本生成可点击的链接,并格式化引用和 em-dashes

你可以在 astro.config.mjs 中自定义 remark 解析 Markdown 的方式。请参阅完整的 Markdown 配置选项列表。

添加 remark 和 rehype 插件

段落标题 添加 remark 和 rehype 插件

Astro 支持添加第三方 remarkrehype 插件来解析 Markdown。这些插件允许你扩展你的 Markdown,以获得新的功能,例如 自动生成目录应用可访问的表情符号标签,以及为你的 Markdown 添加样式

我们鼓励你浏览 awesome-remarkawesome-rehype 来查看流行的插件!请参阅每个插件自己的 README 以获取特定的安装说明。

这个例子将 remark-tocrehype-accessible-emojis 应用于 Markdown 文件:

astro.config.mjs
import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';
import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';
export default defineConfig({
markdown: {
remarkPlugins: [ [remarkToc, { heading: 'toc', maxDepth: 3 } ] ],
rehypePlugins: [rehypeAccessibleEmojis],
},
});

为了自定义插件,请在嵌套数组中提供选项对象。

下面的示例将 标题选项添加到 remarkToc 插件 以更改目录的放置位置,并将 behavior 选项添加到 rehype-autolink-headings 插件以便在标题文本之后添加锚标记。

astro.config.mjs
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default {
markdown: {
remarkPlugins: [ [remarkToc, { heading: "contents"} ] ],
rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }]],
},
}

以编程方式修改 frontmatter

段落标题 以编程方式修改 frontmatter

你可以通过使用 remark 或 rehype 插件 为所有 Markdown 和 MDX 文件添加 frontmatter 属性。

  1. 从插件的 file 参数中将 customProperty 附加到 data.astro.frontmatter 属性:

    example-remark-plugin.mjs
    export function exampleRemarkPlugin() {
    // 所有 remark 和 rehype 插件都返回一个单独的函数
    return function (tree, file) {
    file.data.astro.frontmatter.customProperty = 'Generated property';
    }
    }
  2. 将此插件应用于你的 markdownmdx 集成配置:

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';
    export default defineConfig({
    markdown: {
    remarkPlugins: [exampleRemarkPlugin]
    },
    });

    或者

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { exampleRemarkPlugin } from './example-remark-plugin.mjs';
    export default defineConfig({
    integrations: [
    mdx({
    remarkPlugins: [exampleRemarkPlugin],
    }),
    ],
    });

现在,每个 Markdown 或 MDX 文件都会在其 frontmatter 中有 customProperty,使其在 导入你的 markdown 时以及从 布局中的 Astro.props.frontmatter 属性 中可用。

相关操作指南: 添加阅读时间

从 MDX 扩展 Markdown 配置

段落标题 从 MDX 扩展 Markdown 配置

Astro 的 MDX 集成默认情况下会扩展你的项目的现有 Markdown 配置。要覆盖单个选项,你可以在 MDX 配置中指定它们的等效项。

下面的示例禁用了 GitHub-Flavored Markdown,并为 MDX 文件应用了不同的 remark 插件集:

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
syntaxHighlight: 'prism',
remarkPlugins: [remarkPlugin1],
gfm: true,
},
integrations: [
mdx({
// `syntaxHighlight` 继承自 Markdown
// Markdown `remarkPlugins` 被忽略
// 仅应用 `remarkPlugin2`
remarkPlugins: [remarkPlugin2],
// `gfm` 覆盖为 `false`
gfm: false,
})
]
});

要避免从 MDX 扩展你的 Markdown 配置,请将 extendMarkdownConfig 选项 (默认开启) 设置为 false:

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
remarkPlugins: [remarkPlugin],
},
integrations: [
mdx({
// Markdown 配置现在被忽略
extendMarkdownConfig: false,
// 没有 `remarkPlugins` 应用
})
]
});

Astro 内置支持 ShikiPrism。这为:

Shiki 默认启用,预配置为 github-dark 主题。编译输出将限于内联 style,而不会包含任何冗余的 CSS 类、样式表或客户端 JS。

Shiki 是我们的默认语法高亮器。你可以通过 shikiConfig 对象配置所有选项,如下所示:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
shikiConfig: {
// 选择 Shiki 内置的主题(或添加你自己的主题)
// https://shiki.style/themes
theme: 'dracula',
// 另外,也提供了多种主题
// 查看下面关于使用亮/暗双主题的的说明
themes: {
light: 'github-light',
dark: 'github-dark',
},
// 禁用默认配色
// https://shiki.style/guide/dual-themes#without-default-color
// (添加于 v4.12.0)
defaultColor: false,
// 添加自定义语言
// 注意:Shiki 内置了无数语言,包括 .astro!
// https://shiki.style/languages
langs: [],
// 启用自动换行,以防止水平滚动
wrap: true,
// 添加自定义转换器:https://shiki.style/guide/transformers
// 查找常用转换器:https://shiki.style/packages/transformers
transformers: [],
},
},
});

你可以从本地文件导入自定义主题,而不是使用 Shiki 的预定义主题之一。

astro.config.mjs
import { defineConfig } from 'astro/config';
import customTheme from './my-shiki-theme.json';
export default defineConfig({
markdown: {
shikiConfig: { theme: customTheme },
},
});

我们还建议阅读 Shiki 的主题文档,以了解更多关于主题、深色模式切换或通过 CSS 变量进行样式设置的内容。

如果你想要切换到 'prism' 作为默认值,或者完全禁用语法高亮,你可以使用 markdown.syntaxHighlighting 配置对象:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
// 可以是 'shiki' (默认值)、'prism' 或 false 来禁用语法高亮
syntaxHighlight: 'prism',
},
});

如果你选择使用 Prism,Astro 将应用 Prism 的 CSS 类。请注意,你需要自己的 CSS 样式表,以使语法高亮显示出来!

  1. 从可用的 Prism 主题 中选择一个预制的样式表。

  2. 将此样式表添加到 你的项目的 public/ 目录

  3. 通过 <link> 标签在 布局组件 中的页面的 <head> 中加载此样式表。(参见 Prism 基本用法。)

你还可以访问 Prism 支持的语言列表 以获取选项和用法。

Astro 不包括对 实验性内容集合 之外的远程 Markdown 的内置支持!

要直接获取远程 Markdown 并将其渲染为 HTML,你需要从 NPM 安装并配置你自己的 Markdown 解析器。这 不会 继承你配置的任何 Astro 内置 Markdown 设置。

在项目中实现此功能之前,请确保你了解这些限制,并考虑使用内容集合加载器来代替获取远程 Markdown。

src/pages/remote-example.astro
---
// 示例:从远程 API 请求 Markdown
// 并且在运行时渲染为 HTML
// 使用 "marked" (https://github.com/markedjs/marked)
import { marked } from 'marked';
const response = await fetch('https://raw.githubusercontent.com/wiki/adam-p/markdown-here/Markdown-Cheatsheet.md');
const markdown = await response.text();
const content = marked.parse(markdown);
---
<article set:html={content} />

Astro 将 /src/pages/ 目录 内的任何受支持的文件视为页面,包括 .md 和其他 Markdown 文件类型。

将文件放入此目录或任何子目录中,将使用文件的路径名自动构建页面路由,并显示渲染为 HTML 的 Markdown 内容。

src/pages/page-1.md
---
title: 你好,世界
---
# 嗨!
这个 Markdown 文件在 `your-domain.com/page-1/` 创建了一个页面
也许没有什么样式装点,但 Markdown 还支持这个:
- **加粗**_斜体。_
- 列表项
- [链接](https://astro.build)
- <p>HTML 元素</p>
- 还有更多!

为了帮助扩展 Markdown 页面的有限功能,Astro 提供了一个特殊的 frontmatter layout 属性,它是 Astro Markdown 布局组件 的相对路径。如果你的 Markdown 文件位于 src/pages/ 中,请创建一个布局组件并将其添加到此布局属性中,来为你的 Markdown 内容提供一个页面外壳。

src/pages/posts/post-1.md
---
layout: ../../layouts/BlogPostLayout.astro
title: Astro 简介
author: Himanshu
description: 发现 Astro 的魅力之所在!
---
这是一篇使用 Markdown 编写的文章。

此布局组件是一个常规 Astro 组件,具有通过 Astro.props 为你的 Astro 模板 自动提供详细的可用属性 的功能。例如,你可以通过 Astro.props.frontmatter 访问 Markdown 文件的 frontmatter 属性:

src/layouts/BlogPostLayout.astro
---
const {frontmatter} = Astro.props;
---
<html>
<!-- ... -->
<h1>{frontmatter.title}</h1>
<h2>文章作者:{frontmatter.author}</h2>
<p>{frontmatter.description}</p>
<slot /> <!-- Markdown 内容被注入到这里 -->
<!-- ... -->
</html>

你也可以在布局组件中 为你的 Markdown 设置样式

阅读更多关于 Markdown 布局 的内容。
贡献

你有什么想法?

社区