Пропустить до содержимого

Markdown & MDX

Markdown обычно используется для создания текстового контента, такого как записи в блогах и документация. Astro имеет встроенную поддержку стандартных файлов Markdown (.md).

С интеграцией @astrojs/mdx integration (EN), Astro так же поддерживает MDX (.mdx) файлы, которые предоставляют дополнительные функции, такие как поддержка выражений JavaScript и компонентов в вашем Markdown контенте.

Используйте один или оба типа файлов, чтобы писать Markdown контент!

Astro определяет любые .md или .mdx файлы внутри директории /src/pages/ как страницы. Размещение файла в этой директории или любой поддиректории автоматически создаст роут страницы, используя путь к файлу.

📚 Прочитать больше о роутинге основанную на файлах.

Чтобы начать использовать Markdown в Astro, добавьте новый файл page-1.md к вашему проекту в папке src/pages/. Скопируйте приведенный ниже базовый шаблон в свой файл, а затем просмотрите отрисованный HTML-код в предварительном просмотре вашего браузера. Обычно, это http://localhost:4321/page-1.

src/pages/page-1.md
---
title: Hello, World
---
# Hi there!
This is your first markdown page. It probably isn't styled much, although
Markdown does support **bold** and _italics._
To learn more about adding a layout to your page, read the next section on **Markdown Layouts.**

Astro предоставляет страницам Markdown и MDX специальное свойство frontmatter для layout, которое определяет относительный путь к Astro компоненту макета. Этот компонент обернет содержимое Markdown, предоставив обертку страницы и любые другие элементы шаблона страницы.

src/pages/page.md
---
layout: ../layouts/BaseLayout.astro
title: "Astro v1 Launch!"
author: "Matthew Phillips"
date: "09 Aug 2022"
---

Типичный макет для страниц Markdown включает в себя:

  1. Свойство frontmatter для доступа к frontmatter страницы и прочим данным. Посмотрите Свойства макета Markdown для получения полного списка доступных свойств.
  2. Слот <slot /> для определения, куда разместить Markdown контент.
src/layouts/BaseLayout.astro
---
// 1. Свойство frontmatter для доступа к frontmatter страницы и прочим данным
const { frontmatter } = Astro.props;
---
<html>
<head>
<!-- Добавление прочих Head элементов, таких как стили, мета-теги. -->
<title>{frontmatter.title}</title>
</head>
<body>
<!-- Добавление прочих UI компонентов здесь, таких как header и footer. -->
<h1>{frontmatter.title} by {frontmatter.author}</h1>
<!-- 2. Отрендеренный HTML будет помещен в слот по умолчанию. -->
<slot />
<p>Written on: {frontmatter.date}</p>
</body>
</html>

Вы можете задать типы для свойств макета через MarkdownLayoutProps:

src/layouts/BaseLayout.astro
---
import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{
// Define frontmatter props here
title: string;
author: string;
date: string;
}>;
// Now, `frontmatter`, `url`, and other Markdown layout properties
// are accessible with type safety
const { frontmatter, url } = Astro.props;
---
<html>
<head>
<meta rel="canonical" href={new URL(url, Astro.site).pathname}>
<title>{frontmatter.title}</title>
</head>
<body>
<h1>{frontmatter.title} by {frontmatter.author}</h1>
<slot />
<p>Written on: {frontmatter.date}</p>
</body>
</html>

Markdown макет имеет доступ к следующей информации, через Astro.props:

  • file - Абсолютный путь к файлу (т.е. /home/user/projects/.../file.md).
  • url - URL к странице, если это страница (т.е. /en/guides/markdown-content).
  • frontmatter - frontmatter из Markdown или MDX документа.
    • frontmatter.file - Такой же, как верхне-уровневое свойство file.
    • frontmatter.url - Tакой же, как верхне-уровневое свойствоurl.
  • headings - Список заголовков (h1 -> h6) в Markdown документе с соответствующими метаданными. Этот список соответствует типу: { depth: number; slug: string; text: string }[].
  • rawContent() - Функция, которая возвращает необработанный документ Markdown в виде строки.
  • compiledContent() - Функция, которая возвращает документ Markdown, скомпилированный в HTML-строку.

Пример поста в блоге может передавать следующий Astro.props объект в свой макет:

Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** Frontmatter from a blog post */
title: "Astro 0.18 Release",
date: "Tuesday, July 27 2021",
author: "Matthew Phillips",
description: "Astro 0.18 is our biggest release since Astro launch.",
/** Generated values */
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/"
},
headings: [
{
"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>",
}

Пример: Использование одного макета для файлов .md, .mdx и .astro

Раздел, озаглавленный Пример: Использование одного макета для файлов .md, .mdx и .astro

Единый макет Astro может быть написан для получения объекта frontmatter из файлов .md и .mdx, а также любых именованных свойств, переданных из .astro файлов.

В приведенном ниже примере макет отобразит заголовок страницы либо из компонента Astro, передающего атрибут title, либо из frontmatter свойства title:

src/components/MyLayout.astro
---
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
<head></head>
<body>
<h1>{title}</h1>
<slot />
</body>
</html>

Astro автоматически добавит автоматически сгенерированные идентификаторы ко всем заголовкам в файлах Markdown, используя github-slugger. Но, если указан пользовательский идентификатор, он не будет переопределен.

Эти дочерние элементы будут добавлены после выполнения всех остальных плагинов, поэтому, если у вас есть плагин типа rehype-toc, которому нужны идентификаторы, вам следует добавить свой собственный плагин для блокировки (например, rehype-slug).

draft: true - это необязательное frontmatter свойство, которое помечает отдельную страницу или публикацию .md как “неопубликованную”. По умолчанию эта страница будет исключена из сборки сайта.

Страницы Markdown без свойства draft или страницы с draft: false будут включены в сборку.

src/pages/post/blog-post.md
---
layout: ../../layouts/BaseLayout.astro
title: My Blog Post
draft: true
---
This is my in-progress blog post.
No page will be built for this post.
To build and publish this post:
- update the frontmatter to `draft: false` or
- remove the `draft` property entirely.

Чтобы исключить черновики из архива или списка последних постов, вы можете отфильтровать результаты, возвращаемые вашим Astro.glob().

const posts = await Astro.glob('../pages/post/*.md');
const nonDraftPosts = posts.filter((post) => !post.frontmatter.draft);

⚙️ Чтобы включить создание черновиков:

Добавьте drafts: true в markdown, в файле astro.config.mjs

astro.config.mjs
export default defineConfig({
markdown: {
drafts: true,
},
});

Пожалуйста, установите официальную интеграцию @astros/mdx (EN), чтобы использовать:

Astro включает в себя полную поддержку MDX, в официальной интеграции @astros / mdx. Смотрите руководство по интеграции MDX (EN) для дополнительной информации по интеграции, которая поддерживает устаревшие функции из предыдущего раздела и улучшает ваш Markdown контент.

С интеграцией @astrojs/mdx вы можете использовать переменные и выражения JSX в файлах MDX (.mdx).

С интеграцией @astrojs/mdx, вы можете использовать компоненты Astro или других UI фреймворков в MDX (.mdx) файлах точно так же, как вы бы использовали их в любом другом компоненте Astro (EN).

Не забудьте добавить client:directive, если это необходимо!

Вы можете импортировать файлы Markdown и MDX непосредственно в свои Astro файлы! Вы можете импортировать одну конкретную страницу с помощью import или несколько страниц с помощью Astro.glob().

src/pages/index.astro
---
// Импорт markdown. Динамический import() так же поддерживается!
import * as greatPost from '../pages/post/great-post.md';
// Вы можете импортировать несколько страниц с помощью Astro.glob
const posts = await Astro.glob('../pages/post/*.md');
---
A Great Post: <a href={greatPost.url}>{greatPost.frontmatter.title}</a>
<ul>
{posts.map(post => <li>{post.frontmatter.title}</li>)}
</ul>

Вы можете дополнительно указать тип для переменной frontmatter, используя TypeScript дженерик:

src/pages/index.astro
---
interface Frontmatter {
title: string;
description?: string;
}
const posts = await Astro.glob<Frontmatter>('../pages/post/*.md');
---
<ul>
{posts.map(post => <li>{post.frontmatter.title}</li>)}
<!-- post.frontmatter.title will be `string`! -->
</ul>

Каждый файл Markdown экспортирует следующие свойства.

Содержит любые данные, указанные в YAML frontmatter этого файла.

Абсолютный путь к этому файлу (т.е. /home/user/projects/.../file.md).

Если это страница, URL страницы (т.е. /en/guides/markdown-content).

Асинхронная функция, которая возвращает заголовки в Markdown файле. Ответ соответствует типу:

{ depth: number; slug: string; text: string }[]

Функция, которая возвращает содержимое файла в формате Markdown (исключая блок frontmatter) в виде строки.

Функция, которая возвращает спарсенный HTML-документ в виде строки. Примечание: сюда не входят макеты, настроенные в вашем frontmatter! Только сам документ markdown будет возвращен в формате HTML.

Компонент, который возвращает полное отрендеренное содержимое файла Markdown. Пример:

src/pages/content.astro
---
import {Content as PromoBanner} from '../components/promoBanner.md';
---
<h2>Today's promo</h2>
<PromoBanner />

При использовании getStaticPaths и Astro.glob() для создания страниц из файлов Markdown вы можете передать компонент <Content/> через props страницы. Затем вы можете извлечь компонент из Astro.props и отобразить его в своем шаблоне.

src/pages/[slug].astro
---
export async function getStaticPaths() {
const posts = await Astro.glob('../posts/**/*.md')
return posts.map(post => ({
params: {
slug: post.frontmatter.slug
},
props: {
post
},
}))
}
const { Content } = Astro.props.post
---
<article>
<Content/>
</article>

Поддержка Markdown в Astro осуществляется с помощью remark, мощный инструмент синтаксического анализа и обработки с активной экосистемой. Другие анализаторы Markdown, такие как Pandoc и markdown-it, в настоящее время не поддерживаются.

Вы можете настроить то, как remark парсит ваш Markdown, в astro.config.mjs. Смотрите справочную документацию (EN) для получения полной информации о конфигурации или следуйте нашим руководствам ниже о том, как добавлять remark плагины и настраивать подсветку синтаксиса.

Astro поддерживает сторонние плагины remark и rehype для Markdown. Эти плагины позволяют вам расширить свой Markdown новыми возможностями, как автоматическое создание оглавления, использование emoji с a11y и многое другое. Мы рекомендуем вам просмотреть awesome-remark и awesome-rehype для поиска плагинов!

В этом примере включаются remark-toc и rehype-minify плагины. Инструкции по установке смотрите в README каждого проекта.

astro.config.mjs
import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';
import rehypeMinifyHtml from 'rehype-minify';
export default defineConfig({
markdown: {
remarkPlugins: [remarkToc],
rehypePlugins: [rehypeMinifyHtml],
// Preserve Astro's default plugins: GitHub-flavored Markdown and Smartypants
// default: false
extendDefaultPlugins: true,
},
}

Содержимое Markdown преобразуется в HTML с помощью remark-rehype, который имеет несколько опций.

Вы можете использовать параметры remark-rehype в вашем конфигурационном файле следующим образом:

astro.config.mjs
export default {
markdown: {
remarkRehype: {
footnoteLabel: 'Catatan kaki',
footnoteBackLabel: 'Kembali ke konten',
},
},
};

Возможно, вы захотите добавить свойства frontmatter в свои файлы Markdown программно. Используя плагины remark или rehype, вы можете сгенерировать эти свойства на основе содержимого файла.

Вы можете добавить к свойству data.astro.frontmatter аргумент file вашего плагина следующим образом:

example-remark-plugin.mjs
export function exampleRemarkPlugin() {
// All remark and rehype plugins return a separate function
return function (tree, file) {
file.data.astro.frontmatter.customProperty = 'Generated property';
}
}

После подключения плагина к вашей markdown конфигурации:

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

…каждый файл Markdown будет иметь customProperty в frontmatter! Это доступно при импорте вашего markdown и из свойства Astro.props.frontmatter в ваших макетах.

Вы можете использовать плагин remark, чтобы добавить время чтения к вашему frontmatter. Мы рекомендуем два пакета:

  • reading-time чтобы рассчитать минуты чтения
  • mdast-util-to-string чтобы извлечь весь текст из вашего markdown
Terminal window
npm i reading-time mdast-util-to-string

Мы можем использовать эти пакеты с плагином remark следующим образом:

remark-reading-time.mjs
import getReadingTime from 'reading-time';
import { toString } from 'mdast-util-to-string';
export function remarkReadingTime() {
return function (tree, { data }) {
const textOnPage = toString(tree);
const readingTime = getReadingTime(textOnPage);
// readingTime.text will give us minutes read as a friendly string,
// i.e. "3 min read"
data.astro.frontmatter.minutesRead = readingTime.text;
};
}

Как только вы примените этот плагин к своей конфигурации:

astro.config.mjs
import { remarkReadingTime } from './remark-reading-time.mjs';
export default {
markdown: {
remarkPlugins: [remarkReadingTime],
},
};

…все документы Markdown будут иметь рассчитанные minutesRead. Вы можете использовать это, чтобы включить баннер “X минут чтения” в макет markdown, например:

src/layouts/BlogLayout.astro
---
const { minutesRead } = Astro.props.frontmatter;
---
<html>
<head>...</head>
<body>
<p>{minutesRead}</p>
<slot />
</body>
</html>

Astro идет со встроенной поддержкой для Shiki и Prism. Это обеспечивает подсветку синтаксиса для:

  • все обрамления кода (```) в Markdown (.md) и MDX (.mdx) файле.
  • содержимое компонента <Code /> (EN) (Shiki) или компонента <Prism /> (EN) (Prism).

Shiki включен по умолчанию, предварительно настроен с темой github-dark. Скомпилированный вывод будет ограничен инлайновым style, без каких-либо посторонних классов CSS, таблиц стилей или JS на стороне клиента.

Если вы решите использовать Prism, вместо этого мы применим CSS-классы Prism. Обратите внимание, что вам необходимо создать свой собственный CSS, чтобы появилась подсветка синтаксиса! Смотрите раздел по конфигурации Prism для получения более подробной информации.

Shiki - это наш инструмент подсветки синтаксиса по умолчанию. Если вы хотите переключиться на 'prism' или полностью отключить подсветку синтаксиса, вы можете использовать объект конфигурации markdown:

astro.config.mjs
export default {
markdown: {
// Can be 'shiki' (default), 'prism' or false to disable highlighting
syntaxHighlight: 'prism',
},
};

При использовании Shiki вы будете настраивать все параметры с помощью объекта shikiConfig следующим образом:

astro.config.mjs
export default {
markdown: {
shikiConfig: {
// Choose from Shiki's built-in themes (or add your own)
// https://github.com/shikijs/shiki/blob/main/docs/themes.md
theme: 'dracula',
// Add custom languages
// Note: Shiki has countless langs built-in, including .astro!
// https://github.com/shikijs/shiki/blob/main/docs/languages.md
langs: [],
// Enable word wrap to prevent horizontal scrolling
wrap: true,
},
},
};

Мы также предлагаем углубиться в их документацию по темизации чтобы ознакомится с загрузкой пользовательской темы, с переключателем “светлого и темного” режима или стилизацию через переменные CSS.

При использовании Prism вам нужно будет добавить таблицу стилей в свой проект для подсветки синтаксиса. Если вы только начинаете и предпочитаете использовать Prism вместо Shiki, мы предлагаем:

  1. Установить syntaxHighlight: 'prism' в вашем конфиге @astrojs/markdown-remark.
  2. Выбор готовой таблицы стилей из доступных тем Prism.
  3. Добавить эту таблицу стилей в public/ вашего проекта/.
  4. Добавьте это в ваш <head> (EN) через тег <link>.

Вы также можете посетить список языков, поддерживаемых Prism для получения информации о параметрах.

Astro был в первую очередь разработан для локальных файлов Markdown, которые хранятся внутри вашего проекта. Однако могут быть определенные случаи, когда вам необходимо получить Markdown из удаленного источника. Например, вам может потребоваться извлечь и отобразить Markdown из удаленного API при создании вашего веб-сайта (или когда пользователь делает запрос на ваш веб-сайт, при использовании SSR (EN)).

Astro не включает встроенную поддержку удаленного Markdown! Чтобы получить удаленный Markdown и отобразить его в HTML, вам нужно будет установить и настроить свой собственный парсер Markdown из npm. Это не будет зависеть ни от каких встроенных параметров Markdown и MDX, которые вы настроили. Убедитесь, что вы понимаете эти ограничения, прежде чем внедрять это в свой проект.

src/pages/remote-example.astro
---
// Example: Fetch Markdown from a remote API
// and render it to HTML, at runtime.
// Using "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} />