@astrojs/markdoc
Эта интеграция Astro включает использование Markdoc для создания компонентов, страниц и записей коллекций контента.
Почему Markdoc?
Заголовок раздела «Почему Markdoc?»Markdoc позволяет расширять Markdown с помощью компонентов Astro. Если у вас уже есть контент, написанный в Markdoc, эта интеграция позволит перенести эти файлы в проект Astro через коллекции контента.
Установка
Заголовок раздела «Установка»Astro включает команду astro add для автоматической настройки официальных интеграций. Если вы предпочитаете, вы можете установить интеграции вручную.
Запустите одну из следующих команд в новом окне терминала.
npx astro add markdocpnpm astro add markdocyarn astro add markdocЕсли у вас возникнут какие-либо проблемы, не стесняйтесь сообщать нам о них на GitHub и попробуйте выполнить шаги ручной установки ниже.
Ручная установка
Заголовок раздела «Ручная установка»Сначала установите пакет @astrojs/markdoc:
npm install @astrojs/markdocpnpm add @astrojs/markdocyarn add @astrojs/markdocЗатем подключите интеграцию в вашем astro.config.* через свойство integrations:
import { defineConfig } from 'astro/config';import markdoc from '@astrojs/markdoc';export default defineConfig({ // ... integrations: [markdoc()],});Интеграция с редактором VS Code
Заголовок раздела «Интеграция с редактором VS Code»Если вы используете VS Code, есть официальное расширение языка Markdoc с подсветкой синтаксиса и автодополнением для настроенных тегов. Подробнее см. языковой сервер на GitHub.
Чтобы настроить расширение, создайте файл markdoc.config.json в корне проекта со следующим содержимым:
[ { "id": "my-site", "path": "src/content", "schema": { "path": "markdoc.config.mjs", "type": "esm", "property": "default", "watch": true } }]Укажите markdoc.config.mjs как файл конфигурации через объект schema и задайте, где хранятся Markdoc файлы, через path. Поскольку Markdoc используется только с коллекциями контента, удобно указывать src/content.
Использование
Заголовок раздела «Использование»Markdoc файлы можно использовать только внутри коллекций контента. Добавляйте записи в любую коллекцию, используя расширение .mdoc:
Директорияsrc/
Директорияcontent/
Директорияdocs/
- why-markdoc.mdoc
- quick-start.mdoc
Затем запрашивайте вашу коллекцию через API коллекций контента:
---import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');const { Content } = await render(entry);---
<!--Access frontmatter properties with `data`--><h1>{entry.data.title}</h1><!--Render Markdoc contents with the Content component--><Content />Передача переменных Markdoc
Заголовок раздела «Передача переменных Markdoc»Иногда нужно передать переменные в контент. Это полезно, например, для SSR-параметров, A/B тестов и т.п.
Переменные можно передать как пропсы в компонент Content:
---import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');const { Content } = await render(entry);---
<!--Pass the `abTest` param as a variable--><Content abTestGroup={Astro.params.abTestGroup} />Теперь abTestGroup доступен как переменная в docs/why-markdoc.mdoc:
{% if $abTestGroup === 'image-optimization-lover' %}
Let me tell you about image optimization...
{% /if %}Чтобы сделать переменную глобальной для всех Markdoc файлов, можно использовать атрибут variables в markdoc.config.mjs|ts:
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ variables: { environment: process.env.IS_PROD ? 'prod' : 'dev', },});Доступ к frontmatter из Markdoc контента
Заголовок раздела «Доступ к frontmatter из Markdoc контента»Чтобы получить доступ к frontmatter, можно передать data записи как переменную при рендеринге:
---import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');const { Content } = await render(entry);---
<Content frontmatter={entry.data} />Теперь это доступно как $frontmatter в Markdoc.
Рендеринг компонентов
Заголовок раздела «Рендеринг компонентов»@astrojs/markdoc предоставляет опции конфигурации, чтобы использовать возможности Markdoc и подключать UI-компоненты к вашему контенту.
Использование компонентов Astro как тегов Markdoc
Заголовок раздела «Использование компонентов Astro как тегов Markdoc»Вы можете настроить теги Markdoc, которые будут сопоставлены с компонентами .astro. Добавьте новый тег, создав файл markdoc.config.mjs|ts в корне проекта и настроив tags.
Этот пример рендерит компонент Aside и позволяет передавать проп type как строку:
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ tags: { aside: { render: component('./src/components/Aside.astro'), attributes: { // Markdoc requires type defs for each attribute. // These should mirror the `Props` type of the component // you are rendering. // See Markdoc's documentation on defining attributes // https://markdoc.dev/docs/attributes#defining-attributes type: { type: String }, }, }, },});Этот компонент можно использовать в Markdoc файлах через тег {% aside %}. Дочерний контент будет передан в слот по умолчанию:
# Welcome to Markdoc 👋
{% aside type="tip" %}
Use tags like this fancy "aside" to add some _flair_ to your docs.
{% /aside %}Клиентские UI-компоненты
Заголовок раздела «Клиентские UI-компоненты»Теги и nodes ограничены .astro файлами. Чтобы встроить клиентские UI-компоненты, используйте обертку .astro, которая рендерит framework-компонент с нужной директивой client:.
Этот пример оборачивает React компонент Aside.tsx в компонент ClientAside.astro:
---import Aside from './Aside';---
<Aside {...Astro.props} client:load />Этот Astro компонент можно передать в render для любого тега или node в конфигурации:
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ tags: { aside: { render: component('./src/components/ClientAside.astro'), attributes: { type: { type: String }, }, }, },});Компоненты Astro из npm пакетов и TypeScript файлов
Заголовок раздела «Компоненты Astro из npm пакетов и TypeScript файлов»Иногда нужно использовать Astro компоненты, доступные как именованные экспорты из TypeScript/JavaScript файлов. Это распространено для npm пакетов и дизайн-систем.
Вы можете передать имя экспорта вторым аргументом в component():
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ tags: { tabs: { render: component('@astrojs/starlight/components', 'Tabs'), }, },});Внутри будет сгенерирован следующий import:
import { Tabs } from '@astrojs/starlight/components';Partials в Markdoc
Заголовок раздела «Partials в Markdoc»Тег {% partial /%} позволяет рендерить другие .mdoc файлы внутри Markdoc контента.
Это удобно для переиспользования фрагментов между документами и позволяет иметь .mdoc файлы, которые не соответствуют схеме коллекции.
Используйте префикс _ для partial файлов и директорий. Это исключит их из запросов коллекций контента.
Пример partial файла с футером для записей блога:
Social links:
- [Twitter / X](https://twitter.com/astrodotbuild)- [Discord](https://astro.build/chat)- [GitHub](https://github.com/withastro/astro)Используйте {% partial /%} внизу записи блога. В атрибут file передайте путь к файлу (относительный путь или alias):
# My Blog Post
{% partial file="./_footer.mdoc" /%}Подсветка синтаксиса
Заголовок раздела «Подсветка синтаксиса»@astrojs/markdoc предоставляет расширения Shiki и Prism для подсветки блоков кода.
Подключите расширение shiki() в extends Markdoc конфигурации. Опционально можно передать объект конфигурации shiki:
import { defineMarkdocConfig } from '@astrojs/markdoc/config';import shiki from '@astrojs/markdoc/shiki';
export default defineMarkdocConfig({ extends: [ shiki({ // Choose from Shiki's built-in themes (or add your own) // Default: 'github-dark' // https://shiki.style/themes theme: 'dracula', // Enable word wrap to prevent horizontal scrolling // Default: false wrap: true, // Pass custom languages // Note: Shiki has countless langs built-in, including `.astro`! // https://shiki.style/languages langs: [], }), ],});Подключите prism() в extends:
import { defineMarkdocConfig } from '@astrojs/markdoc/config';import prism from '@astrojs/markdoc/prism';
export default defineMarkdocConfig({ extends: [prism()],});Пользовательские nodes / элементы Markdoc
Заголовок раздела «Пользовательские nodes / элементы Markdoc»Вы можете захотеть рендерить стандартные элементы Markdown (например параграфы или выделение) как Astro компоненты. Для этого можно настроить Markdoc node. Если node принимает атрибуты, они будут доступны как пропсы.
Пример: рендерить blockquote через кастомный Quote.astro:
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ nodes: { blockquote: { ...nodes.blockquote, // Apply Markdoc's defaults for other options render: component('./src/components/Quote.astro'), }, },});Пользовательские заголовки
Заголовок раздела «Пользовательские заголовки»@astrojs/markdoc автоматически добавляет anchor-ссылки к заголовкам и генерирует список headings через API коллекций контента. Чтобы дополнительно настроить, как рендерятся заголовки, можно применить Astro компонент как Markdoc node.
Пример: рендерить заголовки компонентом Heading.astro:
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ nodes: { heading: { ...nodes.heading, // Preserve default anchor link generation render: component('./src/components/Heading.astro'), }, },});Все заголовки Markdown будут рендерить Heading.astro и передавать следующие attributes как пропсы:
level: numberуровень заголовка 1 - 6id: stringid, сгенерированный из текста заголовка (соответствуетslug, который генерируется функциейrender())
Например, ### Level 3 heading! передаст level: 3 и id: 'level-3-heading'.
Пользовательские компоненты изображений
Заголовок раздела «Пользовательские компоненты изображений»Компонент <Image /> из Astro нельзя использовать напрямую в Markdoc. Однако можно настроить Astro компонент, чтобы он переопределял стандартный image node (когда используется ![]()), или создать пользовательский тег Markdoc для изображения, чтобы указывать дополнительные атрибуты.
Переопределить стандартный image node Markdoc
Заголовок раздела «Переопределить стандартный image node Markdoc»Чтобы переопределить стандартный image node, настройте .astro компонент, который будет рендериться вместо <img>.
-
Создайте компонент
MarkdocImage.astro, который передастsrcиaltв<Image />:src/components/MarkdocImage.astro ---import type { ImageMetadata } from "astro";import { Image } from "astro:assets";interface Props {src: ImageMetadata;alt: string;}const { src, alt } = Astro.props;---<Image src={src} alt={alt} /> -
Для удаленных изображений
<Image />требуетwidthиheight, которые нельзя передать синтаксисом![](). Чтобы избежать ошибок, отрендерите обычный<img>, еслиsrc- это URL строкой:src/components/MarkdocImage.astro ---import type { ImageMetadata } from "astro";import { Image } from "astro:assets";interface Props {src: ImageMetadata | string;alt: string;}const { src, alt } = Astro.props;---<Image src={src} alt={alt} />{typeof src === 'string' ? <img src={src} alt={alt} /> : <Image src={src} alt={alt} />} -
Настройте Markdoc, чтобы переопределить image node и рендерить
MarkdocImage.astro:markdoc.config.mjs import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';export default defineMarkdocConfig({nodes: {image: {...nodes.image, // Apply Markdoc's defaults for other optionsrender: component('./src/components/MarkdocImage.astro'),},},}); -
Теперь синтаксис
![]()в любом.mdocбудет использовать<Image />для локальных изображений. Удаленные изображения по-прежнему можно использовать, но они будут рендериться как<img>.src/content/blog/post.mdoc <!-- Optimized by <Image /> --><!-- Unoptimized <img> -->
Создать пользовательский тег изображения Markdoc
Заголовок раздела «Создать пользовательский тег изображения Markdoc»Тег image в Markdoc позволяет задавать дополнительные атрибуты, которые нельзя выразить через ![](). Например, пользовательские image-теги позволяют использовать <Image /> для удаленных изображений, которым нужны width и height.
Следующие шаги создают пользовательский image-тег, который рендерит <figure> с подписью и оптимизирует изображение через <Image />.
-
Создайте компонент
MarkdocFigure.astro:src/components/MarkdocFigure.astro ---import type { ImageMetadata } from "astro";import { Image } from "astro:assets";interface Props {src: ImageMetadata | string;alt: string;width: number;height: number;caption: string;}const { src, alt, width, height, caption } = Astro.props;---<figure><Image {src} {alt} {width} {height} />{caption && <figcaption>{caption}</figcaption>}</figure> -
Настройте кастомный image-тег:
markdoc.config.mjs import { component, defineMarkdocConfig, nodes } from '@astrojs/markdoc/config';export default defineMarkdocConfig({tags: {image: {attributes: {width: {type: String,},height: {type: String,},caption: {type: String,},...nodes.image.attributes},render: component('./src/components/MarkdocFigure.astro'),},},}); -
Используйте
imageв.mdoc:{% image src="./astro-logo.png" alt="Astro Logo" width="100" height="100" caption="a caption!" /%}
Продвинутая конфигурация Markdoc
Заголовок раздела «Продвинутая конфигурация Markdoc»Файл markdoc.config.mjs|ts принимает все опции конфигурации Markdoc, включая теги и функции.
Вы можете передать эти опции в defineMarkdocConfig():
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ functions: { getCountryEmoji: { transform(parameters) { const [country] = Object.values(parameters); const countryToEmojiMap = { japan: '🇯🇵', spain: '🇪🇸', france: '🇫🇷', }; return countryToEmojiMap[country] ?? '🏳'; }, }, },});Теперь вы можете вызывать эту функцию из любого Markdoc контента:
¡Hola {% getCountryEmoji("spain") %}!Задать корневой HTML элемент
Заголовок раздела «Задать корневой HTML элемент»По умолчанию Markdoc оборачивает документ в <article>. Это можно изменить в node document. Можно указать имя HTML элемента или null, чтобы убрать обертку:
import { defineMarkdocConfig, nodes } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ nodes: { document: { ...nodes.document, // Apply defaults for other options render: null, // default 'article' }, },});Опции конфигурации интеграции
Заголовок раздела «Опции конфигурации интеграции»Интеграция Astro Markdoc отвечает за настройку опций Markdoc и возможностей, которые недоступны только через markdoc.config.js.
allowHTML
Заголовок раздела «allowHTML»Тип: boolean
По умолчанию: false
@astrojs/markdoc@0.4.4
Позволяет писать HTML-разметку рядом с Markdoc тегами и nodes.
По умолчанию Markdoc не распознает HTML-разметку как семантический контент.
Чтобы получить опыт, более похожий на Markdown, где можно использовать HTML элементы внутри контента, установите allowHTML:true в опциях интеграции markdoc.
import { defineConfig } from 'astro/config'; import markdoc from '@astrojs/markdoc';
export default defineConfig({ // ... integrations: [markdoc({ allowHTML: true })], });Когда allowHTML включен, HTML-разметка внутри документов Markdoc будет рендериться как реальные HTML-элементы (включая <script>), что открывает векторы атак вроде XSS. Убедитесь, что HTML-разметка приходит из доверенных источников.
ignoreIndentation
Заголовок раздела «ignoreIndentation»Тип: boolean
По умолчанию: false
@astrojs/markdoc@0.7.0
По умолчанию любой контент с отступом в четыре пробела трактуется как блок кода. Это затрудняет использование произвольных уровней отступов для улучшения читабельности сложных документов.
При использовании вложенных тегов Markdoc бывает полезно делать отступы внутри тегов, чтобы уровень вложенности был понятен. Для поддержки произвольных отступов нужно отключить code blocks, основанные на отступах, и изменить несколько правил парсинга. Это можно сделать через ignoreIndentation.
import { defineConfig } from 'astro/config'; import markdoc from '@astrojs/markdoc';
export default defineConfig({ // ... integrations: [markdoc({ ignoreIndentation: true })], });# Welcome to Markdoc with indented tags 👋
# Note: Can use either spaces or tabs for indentation
{% custom-tag %}{% custom-tag %} ### Tags can be indented for better readability
{% another-custom-tag %} This is easier to follow when there is a lot of nesting {% /another-custom-tag %}
{% /custom-tag %}{% /custom-tag %}Примеры
Заголовок раздела «Примеры»- Стартовый шаблон Astro Markdoc показывает, как использовать Markdoc в проекте Astro.