Копирование кода

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


Синтаксис блоков кода

В MDX поддерживается стандартный Markdown-синтаксис для блоков кода:

```javascript
console.log('Hello, MDX!');

В этом примере:

- Тройные обратные апострофы (\`\`\`) обозначают начало и конец блока кода.
- Язык (`javascript`) используется для подсветки синтаксиса.
- Содержимое между апострофами рендерится как код с сохранением форматирования и отступов.

Ключевой момент: MDX автоматически обрабатывает такие блоки как JSX-элементы, поэтому их можно стилизовать и оборачивать дополнительными компонентами.

---

### Использование компонента `pre` и `code`

Для более точного контроля над отображением кода можно использовать нативные HTML-элементы `pre` и `code` внутри MDX:

```jsx
<pre>
  <code className="language-js">
    {`function greet(name) {
      return \`Hello, \${name}!\`;
    }`}
  </code>
</pre>

Особенности:

  • pre сохраняет форматирование и переносы строк.
  • code может содержать атрибут className для подсветки синтаксиса через библиотеки, такие как Prism или Highlight.js.
  • Вставка кода в виде строки с помощью шаблонных литералов позволяет избежать ошибок при интерпретации JSX.

Добавление кнопки копирования

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

import { useState } from 'react';

function CopyButton({ code }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = () => {
    navigator.clipboard.writeText(code).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  return (
    <button onCl ick={handleCopy}>
      {copied ? 'Скопировано!' : 'Копировать'}
    </button>
  );
}

Интеграция с блоком кода:

<pre>
  <code className="language-js">
    {`const sum = (a, b) => a + b;`}
  </code>
  <CopyButton code={`const sum = (a, b) => a + b;`} />
</pre>

Особенности подхода:

  • Используется API navigator.clipboard для безопасного копирования текста.
  • Компонент CopyButton является универсальным и может применяться к любому коду.
  • Состояние copied обеспечивает динамическую обратную связь пользователю.

Автоматизация через обёртки

Для документации с большим количеством блоков кода удобно создать обёртку, объединяющую отображение и кнопку копирования:

export function CodeBlock({ language, children }) {
  return (
    <div className="code-block">
      <pre>
        <code className={`language-${language}`}>
          {children}
        </code>
      </pre>
      <CopyButton code={children} />
    </div>
  );
}

Использование в MDX:

<CodeBlock language="js">
{`function multiply(a, b) {
  return a * b;
}`}
</CodeBlock>

Преимущества:

  • Единый стиль для всех блоков кода.
  • Упрощение управления кнопками копирования.
  • Возможность подключать сторонние библиотеки подсветки синтаксиса в одном месте.

Подсветка синтаксиса

Для подсветки синтаксиса кода чаще всего используют Prism или Highlight.js. Интеграция с MDX:

import Prism from 'prismjs';
import 'prismjs/themes/prism-tomorrow.css';
import { useEffect } from 'react';

function HighlightedCode({ language, children }) {
  useEffect(() => {
    Prism.highlightAll();
  }, []);

  return (
    <pre className={`language-${language}`}>
      <code>{children}</code>
    </pre>
  );
}

Особенности:

  • useEffect гарантирует, что подсветка применяется после рендера.
  • Поддерживаются разные темы и языки программирования.
  • Совместимо с кнопкой копирования, если обернуть её вместе с HighlightedCode.

Советы по удобству использования

  1. Разделение логики и представления: отдельный компонент для кнопки копирования упрощает сопровождение.
  2. Унификация стилей: использование CSS-классов или styled-components позволяет поддерживать консистентный внешний вид всех блоков кода.
  3. Безопасность: проверять размер копируемого кода, чтобы избежать проблем с большим объемом текста в navigator.clipboard.
  4. Масштабируемость: для больших проектов MDX рекомендуется создавать библиотеку собственных компонентов CodeBlock с подсветкой и копированием.

Вывод

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