Перейти к содержимому

13. Markdown и MDX

Astro имеет встроенную поддержку Markdown и MDX — формата, позволяющего использовать JSX-компоненты внутри Markdown файлов. Это делает Astro идеальным для блогов, документации и контент-сайтов.

Любой .md файл в src/pages/ автоматически становится страницей:

src/
pages/
blog/
first-post.md → /blog/first-post
second-post.md → /blog/second-post
about.md → /about

YAML frontmatter в начале файла содержит метаданные страницы:

---
title: Моя первая статья
description: Знакомство с Astro Markdown
pubDate: 2025-01-15
author: Иван Иванов
tags: [astro, web, tutorial]
image:
src: /images/post-cover.jpg
alt: Обложка статьи
draft: false
---
# Моя первая статья
Это содержимое статьи. Frontmatter доступен как `Astro.props` в лейауте.

Доступ к frontmatter в коде:

src/layouts/BlogPost.astro
---
const { title, description, pubDate, author, image } = Astro.props;
const formattedDate = new Date(pubDate).toLocaleDateString('ru-RU');
---
<html>
<head>
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<header>
<img src={image.src} alt={image.alt} />
<h1>{title}</h1>
<p>{author} · {formattedDate}</p>
</header>
<main>
<slot /> <!-- Здесь появится контент Markdown -->
</main>
</body>
</html>

Установка MDX интеграции:

Окно терминала
npx astro add mdx

MDX позволяет импортировать и использовать компоненты прямо в контенте:

---
title: Интерактивный урок
layout: ../layouts/BlogPost.astro
---
import Counter from '../components/Counter.jsx';
import Callout from '../components/Callout.astro';
import { Chart } from '../components/Chart.jsx';
# Интерактивный урок
Обычный текст Markdown работает как всегда.
<Callout type="info">
Это компонент Astro прямо внутри MDX!
</Callout>
Посмотрите на интерактивный счётчик:
<Counter client:visible initialCount={5} />
## Данные в компонентах
export const data = [10, 25, 18, 40, 35];
<Chart data={data} title="Посещаемость" />

Astro использует Shiki по умолчанию (или Prism как альтернативу):

astro.config.mjs
export default defineConfig({
markdown: {
// Shiki (по умолчанию)
shikiConfig: {
theme: 'dracula',
langs: [],
wrap: true,
},
// Или переключитесь на Prism
syntaxHighlight: 'prism',
},
});
Окно терминала
npm install remark-toc rehype-slug rehype-autolink-headings
astro.config.mjs
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default defineConfig({
markdown: {
remarkPlugins: [
[remarkToc, { heading: 'Содержание' }],
],
rehypePlugins: [
rehypeSlug,
[rehypeAutolinkHeadings, { behavior: 'wrap' }],
],
},
});
src/layouts/MarkdownLayout.astro
---
const { frontmatter } = Astro.props;
const { title, pubDate, author, tags } = frontmatter;
---
<html>
<body>
<article class="prose">
<h1>{title}</h1>
<div class="meta">
<time>{new Date(pubDate).toLocaleDateString('ru-RU')}</time>
<span>{author}</span>
</div>
<div class="tags">
{tags.map(tag => <span class="tag">#{tag}</span>)}
</div>
<slot />
</article>
</body>
</html>
---
layout: ../layouts/MarkdownLayout.astro
title: Пример с лейаутом
pubDate: 2025-01-15
author: Иван
tags: [astro, markdown]
---
Контент статьи автоматически рендерится в слот лейаута.