Метаданные блоков кода

В библиотеке Marked поддерживается возможность добавления метаданных к блокам кода, что позволяет расширить стандартный Markdown синтаксис и управлять дополнительными свойствами кода. Метаданные полезны для определения языка, подсветки синтаксиса, атрибутов HTML и других кастомных параметров.


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

Блок кода в Markdown создается с помощью тройных обратных кавычек (```). Стандартный синтаксис выглядит так:

```javascript
console.log("Hello, world!");

Для добавления метаданных используется следующая структура:

```markdown
```[язык] [ключ1=значение1 ключ2=значение2 ...]
код

- `[язык]` — необязательный идентификатор языка, используемый для подсветки синтаксиса.
- `[ключ=значение]` — набор **пар ключ-значение**, которые можно обработать в дальнейшем в HTML-шаблоне или плагинах.

Пример блока с метаданными:

```markdown
```javascript linenumbers=true highlight=2-4
function sum(a, b) {
  return a + b;
}
console.log(sum(2, 3));

В этом примере добавлены два свойства:
- `linenumbers=true` — включает нумерацию строк.
- `highlight=2-4` — подсвечивает строки с 2-й по 4-ю.

---

#### Обработка метаданных в Marked

Библиотека Marked предоставляет **токенизацию и рендеринг блоков кода** через функции `lexer` и `renderer`. Метаданные доступны в объекте токена, который можно использовать для кастомного рендеринга.

Пример использования:

```javascript
import { marked } from 'marked';

const renderer = {
  code(code, infostring, escaped) {
    const [lang, ...metaParts] = infostring.split(/\s+/);
    const meta = {};
    metaParts.forEach(part => {
      const [key, value] = part.split('=');
      if (key && value) meta[key] = value;
    });

    return `<pre class="${lang}" data-meta='${JSON.stringify(meta)}'>${code}</pre>`;
  }
};

marked.use({ renderer });

const markdown = `
\`\`\`javascript linenumbers=true highlight=2-4
function sum(a, b) {
  return a + b;
}
console.log(sum(2, 3));
\`\`\`
`;

console.log(marked(markdown));

Пояснения:

  • infostring содержит строку после тройных кавычек, включая язык и метаданные.
  • Разделение по пробелам позволяет извлечь язык и мета-параметры.
  • Метаданные сохраняются в виде объекта и могут быть переданы в HTML через data-* атрибуты.

Применение метаданных

Метаданные открывают широкие возможности:

  1. Подсветка конкретных строк

    • Атрибут highlight позволяет выделять определённые строки в блоке кода.
    • Используется вместе с библиотеками подсветки типа Prism.js или Highlight.js.
  2. Нумерация строк

    • Атрибут linenumbers активирует нумерацию строк.
    • Можно задать стиль нумерации через CSS, используя data-meta.
  3. Кастомные атрибуты

    • Например, copyable=true для кнопки копирования кода.
    • Любые дополнительные свойства можно передавать через data-meta для обработки на клиенте.

Примеры расширенной работы с метаданными

Подсветка строк через Prism.js:

const renderer = {
  code(code, infostring) {
    const [lang, ...metaParts] = infostring.split(/\s+/);
    const meta = {};
    metaParts.forEach(part => {
      const [key, value] = part.split('=');
      if (key && value) meta[key] = value;
    });

    const highlightedCode = Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup, lang);

    return `<pre class="language-${lang}" data-highlight='${meta.highlight || ""}'>${highlightedCode}</pre>`;
  }
};

Создание копируемых блоков кода:

const renderer = {
  code(code, infostring) {
    const [lang, ...metaParts] = infostring.split(/\s+/);
    const meta = {};
    metaParts.forEach(part => {
      const [key, value] = part.split('=');
      if (key && value) meta[key] = value;
    });

    const copyButton = meta.copyable === 'true' ? '<button class="copy">Copy</button>' : '';
    return `<pre class="language-${lang}">${copyButton}<code>${code}</code></pre>`;
  }
};

Практические советы

  • Использовать единый стандарт метаданных, чтобы парсинг был предсказуемым.
  • Разделять язык и метаданные пробелом, чтобы Marked корректно различал инфостроку.
  • Обрабатывать отсутствующие ключи безопасно, чтобы рендерер не ломался при незаполненных параметрах.
  • Сохранять данные в data-* атрибутах, чтобы фронтенд мог динамически модифицировать блок кода (подсветка, нумерация, кнопки).

Метаданные в Marked позволяют превращать обычные блоки кода в интерактивные и кастомные компоненты, сохраняя совместимость с Markdown и расширяя возможности для фронтенд-разработки.