Глобальная замена компонентов

MDX позволяет использовать компоненты React внутри Markdown, объединяя преимущества разметки и возможностей React. Одной из ключевых функций является возможность глобальной замены компонентов, что позволяет переопределять стандартные элементы Markdown, такие как заголовки, абзацы, ссылки и списки, на кастомные React-компоненты без необходимости менять каждое использование вручную.

Основной принцип

В MDX глобальная замена компонентов осуществляется через объект components, который передаётся в MDXProvider. Этот объект определяет соответствие между стандартными тегами Markdown и пользовательскими компонентами. Например:

import { MDXProvider } from '@mdx-js/react';
import CustomHeading from './CustomHeading';
import CustomParagraph from './CustomParagraph';

const components = {
  h1: CustomHeading,
  p: CustomParagraph,
};

<MDXProvider components={components}>
  <MDXContent />
</MDXProvider>

Здесь все заголовки первого уровня <h1> и абзацы <p> внутри MDX-документа будут автоматически заменены на CustomHeading и CustomParagraph соответственно.

Переопределение нескольких уровней заголовков

MDX позволяет задавать отдельные компоненты для каждого уровня заголовка:

const components = {
  h1: (props) => <h1 style={{ color: 'red' }} {...props} />,
  h2: (props) => <h2 style={{ color: 'blue' }} {...props} />,
  h3: (props) => <h3 style={{ fontStyle: 'italic' }} {...props} />,
};

Такой подход позволяет сохранить визуальное различие заголовков и управлять стилем централизованно.

Кастомизация списков и ссылок

Глобальная замена компонентов не ограничивается только заголовками и параграфами. Можно полностью контролировать отображение списков и ссылок:

const components = {
  a: ({ href, children }) => <CustomLink href={href}>{children}</CustomLink>,
  ul: ({ children }) => <CustomList type="unordered">{children}</CustomList>,
  ol: ({ children }) => <CustomList type="ordered">{children}</CustomList>,
};

В данном примере все ссылки и списки внутри MDX-документа будут использовать кастомные React-компоненты, что упрощает интеграцию с глобальными стилями и компонентной библиотекой.

Вложенные MDX и передача компонентов

MDXProvider позволяет передавать объект компонентов глубоко вниз по дереву вложенных MDX-документов, что особенно полезно для крупных документаций:

<MDXProvider components={components}>
  <ParentMDX>
    <ChildMDX />
  </ParentMDX>
</MDXProvider>

Все элементы, определённые в components, будут применяться рекурсивно к дочерним MDX-документам, если они используют стандартные Markdown-теги.

Смешивание глобальных и локальных компонентов

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

import { MDXProvider } from '@mdx-js/react';
import CustomParagraph from './CustomParagraph';

const GlobalComponents = {
  p: CustomParagraph,
};

const LocalComponents = {
  p: (props) => <CustomParagraph style={{ fontWeight: 'bold' }} {...props} />,
};

<MDXProvider components={GlobalComponents}>
  <MDXContent components={LocalComponents} />
</MDXProvider>

В этом примере глобальная замена задаёт базовую визуализацию абзацев, а локальная модифицирует стиль для конкретного документа.

Практические советы по организации

  • Централизация компонентов: Все кастомные компоненты лучше хранить в отдельной папке components/mdx, чтобы обеспечить единообразие и лёгкое управление.
  • Типизация: При использовании TypeScript рекомендуется типизировать объект components, чтобы получать автодополнение и проверку типов:
import { MDXProviderComponents } from '@mdx-js/react';

const components: MDXProviderComponents = {
  h1: CustomHeading,
  p: CustomParagraph,
};
  • Комбинирование с UI-библиотеками: Глобальная замена позволяет интегрировать MDX с готовыми компонентами из Material UI, Chakra UI или других библиотек, сохраняя единый стиль интерфейса.

Особенности работы с атрибутами

Кастомные компоненты получают все атрибуты исходного HTML-тега, что позволяет добавлять дополнительные пропсы или использовать стилизацию через className или style:

const components = {
  h2: ({ children, ...props }) => (
    <h2 style={{ borderBottom: '2px solid black' }} {...props}>
      {children}
    </h2>
  ),
};

Таким образом, глобальная замена компонентов MDX даёт полный контроль над внешним видом Markdown-документов, объединяет возможности React и облегчает поддержку крупных проектов с единым стилевым оформлением.