Создание простого редактора

Marked — это высокопроизводительная библиотека для парсинга Markdown в JavaScript. Она предназначена для преобразования текста в Markdown в HTML и предоставляет гибкие возможности настройки поведения парсера, включая обработку пользовательских правил, токенизацию и рендеринг. В ядре библиотеки используется токенизация исходного текста и последующее преобразование токенов в HTML.

Для начала работы с Marked достаточно подключить библиотеку через npm:

npm install marked

И импортировать в проект:

import { marked } from 'marked';

Преобразование Markdown в HTML

Базовое использование библиотеки заключается в функции marked():

const markdown = `
# Заголовок первого уровня

Текст с **жирным выделением** и *курсивом*.
`;

const html = marked(markdown);
console.log(html);

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

  • # — обозначает заголовки.
  • **текст** — жирное выделение.
  • *текст* — курсивное выделение.
  • Библиотека корректно обрабатывает списки, цитаты, ссылки и изображения.

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

Marked предоставляет возможность кастомизации вывода через объект Renderer. Это позволяет изменять HTML для конкретных элементов Markdown.

const renderer = new marked.Renderer();

renderer.heading = (text, level) => {
  return `<h${level} class="custom-heading">${text}</h${level}>`;
};

renderer.link = (href, title, text) => {
  return `<a href="${href}" title="${title || ''}" target="_blank">${text}</a>`;
};

const htmlCustom = marked(markdown, { renderer });
console.log(htmlCustom);

Преимущества кастомного рендерера:

  • Возможность добавлять CSS-классы к элементам.
  • Контроль над атрибутами ссылок, изображений и других тегов.
  • Поддержка расширений Markdown с пользовательской логикой.

Работа с опциями

Marked имеет множество опций, которые влияют на поведение парсера:

const options = {
  gfm: true,               // Включение GitHub Flavored Markdown
  breaks: true,            // Перенос строк при одиночном переносе
  smartLists: true,        // Улучшенное форматирование списков
  smartypants: true        // Преобразование кавычек и тире в типографские символы
};

marked.setOptions(options);

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

  • gfm позволяет использовать расширения GitHub Markdown, такие как таблицы и чекбоксы.
  • breaks меняет поведение переноса строк.
  • smartLists обеспечивает корректное оформление вложенных списков.
  • smartypants улучшает типографику текста.

Асинхронный рендеринг

Marked поддерживает асинхронную обработку Markdown, что особенно полезно при работе с большими документами или при необходимости загружать внешние данные (например, из API):

async function renderMarkdown(markdownText) {
  const html = await marked.parse(markdownText);
  return html;
}

Асинхронный метод marked.parse() возвращает промис, который резолвится в готовый HTML-код.

Создание редактора Markdown

Для простого редактора необходимо создать HTML-структуру с полем ввода и контейнером для отображения результата:

<textarea id="editor"></textarea>
<div id="preview"></div>

Далее подключается обработчик событий:

const editor = document.getElementById('editor');
const preview = document.getElementById('preview');

editor.addEventListener('input', () => {
  const markdownText = editor.value;
  preview.innerHTML = marked(markdownText);
});

Особенности реализации:

  • Использование события input обеспечивает мгновенный рендер при каждом вводе.
  • Контейнер preview может быть стилизован для отображения HTML как в редакторах типа GitHub.

Безопасность и XSS

По умолчанию Marked не фильтрует HTML, что может представлять угрозу безопасности. Для безопасного отображения рекомендуется использовать библиотеку DOMPurify:

import DOMPurify from 'dompurify';

const safeHtml = DOMPurify.sanitize(marked(markdownText));
preview.innerHTML = safeHtml;

Преимущества подхода:

  • Очистка потенциально опасного HTML.
  • Сохранение корректного рендеринга Markdown.
  • Подходит для публичных веб-приложений.

Расширение функциональности

Marked позволяет добавлять собственные токены и правила парсинга:

const tokenizer = {
  strong(src) {
    if (src.startsWith('**')) {
      return {
        type: 'strong',
        raw: '**custom**',
        text: 'Custom Strong'
      };
    }
  }
};

marked.use({ tokenizer });

Это открывает возможности для реализации:

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

Итоговое устройство редактора

Комбинация всех вышеописанных возможностей позволяет создать:

  • Редактор с мгновенной визуализацией Markdown.
  • Поддержку расширений GitHub Flavored Markdown.
  • Безопасный вывод HTML с использованием фильтрации.
  • Кастомизацию внешнего вида через Renderer.
  • Расширяемую систему токенов для внедрения новых синтаксисов.

Такой подход делает библиотеку Marked мощным инструментом для создания полноценных веб-редакторов Markdown с высокой производительностью и гибкой настройкой.