Серверный рендеринг

Для использования Markdown-it в проекте на Node.js необходимо установить пакет через npm:

npm install markdown-it

После установки библиотеку подключают следующим образом:

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();

Создание экземпляра MarkdownIt позволяет настраивать поведение парсера, подключать плагины и управлять процессом рендеринга.


Настройка параметров рендеринга

Markdown-it поддерживает множество опций, которые влияют на конечный HTML:

const md = new MarkdownIt({
  html: true,        // разрешить HTML-теги в исходном Markdown
  xhtmlOut: false,   // использовать XHTML-совместимый вывод
  breaks: true,      // преобразовывать переносы строк в 
linkify: true, // автоматически преобразовывать URL в ссылки typographer: true // включить типографские замены (кавычки, тире) });

Ключевые моменты:

  • html — включает поддержку встроенного HTML, что важно при серверном рендеринге сложного контента.
  • linkify — полезно для генерации ссылок без явного Markdown-синтаксиса.
  • typographer — улучшает визуальное качество текста, автоматически заменяя дефисы, кавычки и сокращения.

Основы рендеринга

Для конвертации Markdown в HTML используется метод render:

const markdownString = `
# Заголовок H1

Это **жирный текст** и *курсив*.
`;

const resultHtml = md.render(markdownString);
console.log(resultHtml);

Результатом будет корректно сформированный HTML:

Заголовок H1

Это жирный текст и курсив.

Метод render полностью парсит строку и возвращает HTML. Для больших документов на сервере это ключевой инструмент.


Потоковая обработка Markdown

Markdown-it предоставляет метод parse для получения токенов, что позволяет гибко управлять контентом перед рендерингом:

const tokens = md.parse(markdownString, {});
tokens.forEach(token => {
  console.log(token.type, token.tag, token.content);
});

Применение токенов:

  • Создание кастомного рендерера для особых тегов.
  • Добавление атрибутов к заголовкам или ссылкам.
  • Фильтрация контента для безопасного вывода на сервере.

Кастомизация рендерера

Каждому типу токена можно назначить свой рендер-функционал:

md.renderer.rules.heading_open = (tokens, idx, options, env, self) => {
  const token = tokens[idx];
  token.attrPush(['class', 'custom-heading']);
  return self.renderToken(tokens, idx, options);
};

Такой подход позволяет:

  • Добавлять классы и идентификаторы к элементам.
  • Внедрять JavaScript-обработчики на уровне HTML.
  • Управлять стилями и семантикой контента на сервере.

Плагины и расширения

Markdown-it имеет развитую систему плагинов. Примеры популярных расширений:

  1. markdown-it-footnote — добавляет поддержку сносок.
  2. markdown-it-task-lists — поддержка чекбоксов и списков задач.
  3. markdown-it-anchor — автоматическая генерация якорей для заголовков.

Пример подключения плагина:

const markdownItAnchor = require('markdown-it-anchor');
md.use(markdownItAnchor, {
  permalink: true,
  permalinkSymbol: '¶'
});

Безопасность и фильтрация HTML

При серверном рендеринге критически важно обезопасить вывод HTML:

  • Включение опции html: false предотвращает выполнение встроенного HTML.
  • Использование сторонних библиотек, таких как DOMPurify или sanitize-html, позволяет фильтровать потенциально опасные элементы.

Пример с sanitize-html:

const sanitizeHtml = require('sanitize-html');
const safeHtml = sanitizeHtml(md.render(markdownString));

Производительность

Markdown-it разработан с упором на скорость и масштабируемость:

  • Парсер работает линейно по числу символов Markdown.
  • Поддерживается ленивый рендеринг и потоковая обработка токенов.
  • Возможность кеширования результатов рендеринга для повторного использования при серверной генерации страниц.

Пример кеширования:

const cache = new Map();

function renderMarkdown(markdown) {
  if (cache.has(markdown)) return cache.get(markdown);
  const html = md.render(markdown);
  cache.set(markdown, html);
  return html;
}

Серверная интеграция

Markdown-it легко интегрируется с Express или другими Node.js-фреймворками:

const express = require('express');
const app = express();

app.get('/page', (req, res) => {
  const markdownContent = '# Пример страницы\nТекст страницы';
  const htmlContent = md.render(markdownContent);
  res.send(`${htmlContent}`);
});

app.listen(3000);

Такой подход позволяет генерировать HTML на сервере, обеспечивая SEO-дружественный контент и контроль над безопасностью и стилизацией.