Работа с Markdown в TypeScript: библиотеки, парсеры и инструменты

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в Markdown и TypeScript

Markdown — это легковесный язык разметки, широко используемый для форматирования текста в документации, README-файлах, блогах и чатах. TypeScript, как строго типизированная надстройка над JavaScript, позволяет создавать надёжные и масштабируемые приложения для обработки Markdown. На сайте pythonlib.ru мы рассмотрим лучшие библиотеки и инструменты для работы с Markdown в TypeScript, их возможности и примеры использования.

Популярные библиотеки для парсинга Markdown

Существует несколько зрелых решений для преобразования Markdown в HTML или другие форматы. Рассмотрим три наиболее популярных:

  • marked — быстрый и легковесный парсер с поддержкой синтаксиса GFM (GitHub Flavored Markdown). Имеет встроенные типы для TypeScript.
  • showdown — универсальный конвертер Markdown в HTML с возможностью расширения и настройки.
  • unified (с пакетом remark) — современная экосистема для обработки Markdown на основе AST (абстрактного синтаксического дерева). Позволяет не только парсить, но и анализировать, преобразовывать и форматировать Markdown.

Установка и настройка

Для начала работы установите одну из библиотек через npm. Пример для marked:

npm install marked
npm install @types/marked --save-dev

Для unified с remark потребуется несколько пакетов:

npm install unified remark-parse remark-html
npm install @types/unified @types/remark-parse

Пример: парсинг Markdown с помощью marked

Создадим простую функцию для конвертации Markdown-строки в HTML:

import { marked } from 'marked';

function renderMarkdown(mdContent: string): string {
    return marked.parse(mdContent);
}

const md = `# Заголовок\n\nЭто **жирный** текст и _курсив_.`;
const html = renderMarkdown(md);
console.log(html);
// Вывод: <h1>Заголовок</h1>
// <p>Это <strong>жирный</strong> текст и <em>курсив</em>.</p>

Работа с AST через unified + remark

Библиотека unified позволяет работать с Markdown на уровне дерева. Это полезно для анализа структуры документа, извлечения заголовков или преобразования ссылок.

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkHtml from 'remark-html';

async function mdToHtml(mdContent: string): Promise<string> {
    const file = await unified()
        .use(remarkParse)
        .use(remarkHtml)
        .process(mdContent);
    return String(file);
}

const md = `## Второй уровень\n\nСписок:\n- Пункт 1\n- Пункт 2`;
mdToHtml(md).then(console.log);
// Вывод: <h2>Второй уровень</h2>
// <p>Список:</p>
// <ul>
// <li>Пункт 1</li>
// <li>Пункт 2</li>
// </ul>

Создание редактора Markdown с подсветкой

Для образовательного сайта полезно реализовать интерактивный редактор, в котором пользователь пишет Markdown, а справа видит предварительный просмотр HTML с подсветкой синтаксиса. Используем marked и highlight.js для подсветки блоков кода:

import { marked } from 'marked';
import hljs from 'highlight.js';

// Настройка marked для использования highlight.js
marked.setOptions({
    highlight: (code: string, lang: string) => {
        if (lang && hljs.getLanguage(lang)) {
            return hljs.highlight(code, { language: lang }).value;
        }
        return code; // если язык не указан или не найден
    }
});

function previewMarkdown(mdContent: string): string {
    return marked.parse(mdContent);
}

// Пример использования в браузере (событие input на textarea)
const textarea = document.getElementById('editor') as HTMLTextAreaElement;
const preview = document.getElementById('preview') as HTMLDivElement;

textarea.addEventListener('input', () => {
    preview.innerHTML = previewMarkdown(textarea.value);
});

Типизация и безопасность

TypeScript добавляет строгую типизацию, что помогает избежать ошибок. Например, можно определить тип для конфигурации парсера:

interface MarkdownOptions {
    gfm?: boolean;
    breaks?: boolean;
    sanitize?: boolean; // для безопасности (устарело в новых версиях)
}

function configureParser(opts: MarkdownOptions): void {
    marked.setOptions(opts);
}

configureParser({ gfm: true, breaks: false });                    

Рекомендаций