Для начала работы с библиотекой Marked необходимо установить её через npm:
npm install marked
Импортировать библиотеку в проект можно следующим образом:
import { marked } from 'marked';
После импорта можно настроить глобальные параметры парсера:
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true, // Включение GitHub Flavored Markdown
breaks: false, // Разрешение на перенос строк
sanitize: false, // Автоматическая очистка HTML
smartLists: true, // Интеллектуальные списки
smartypants: false // Замена кавычек и тире на типографские
});
Расширение в Marked позволяет модифицировать или добавлять поведение парсера, например, новые синтаксические конструкции или обработку специальных блоков. Основными способами создания расширения являются:
Токенизатор отвечает за преобразование текста в токены. Пример
токенизатора для распознавания специальных блоков типа
:::note:
const noteTokenizer = {
name: 'note',
level: 'block', // блоковый элемент
start(src) {
return src.match(/:::note/)?.index;
},
tokenizer(src, tokens) {
const rule = /^:::note\s+([\s\S]+?)\s+:::/;
const match = rule.exec(src);
if (match) {
return {
type: 'note',
raw: match[0],
text: match[1].trim()
};
}
}
};
Добавление токенизатора в Marked:
marked.use({ extensions: [noteTokenizer] });
Рендерер отвечает за преобразование токенов в HTML. Для обработки
нового типа токена note необходимо добавить метод в объект
рендерера:
const renderer = {
note(token) {
return `<div class="note">${marked.parseInline(token.text)}</div>`;
}
};
marked.use({ renderer });
Теперь текст вида:
:::note
Это важное уведомление
:::
будет преобразован в:
<div class="note">Это важное уведомление</div>
Marked позволяет использовать несколько расширений одновременно.
Расширения объединяются в массив, передаваемый через
marked.use():
marked.use({
extensions: [noteTokenizer, spoilerTokenizer],
renderer: customRenderer
});
Порядок расширений важен: токенизаторы обрабатываются по очереди, а рендереры – по типу токена.
Каждое расширение можно настраивать по уровню:
div,
section, списки).span, a, em).Также можно определить приоритет обработки, чтобы
новые токены обрабатывались раньше или после стандартных элементов
Markdown. Для этого используется метод start(src) в
токенизаторе, который возвращает позицию первого совпадения.
Создание расширения, которое добавляет и блок note, и
встроенный блок spoiler:
const spoilerTokenizer = {
name: 'spoiler',
level: 'inline',
start(src) { return src.indexOf('||'); },
tokenizer(src) {
const match = /^\|\|([\s\S]+?)\|\|/.exec(src);
if (match) {
return {
type: 'spoiler',
raw: match[0],
text: match[1]
};
}
}
};
const customRenderer = {
note(token) {
return `<div class="note">${marked.parseInline(token.text)}</div>`;
},
spoiler(token) {
return `<span class="spoiler">${token.text}</span>`;
}
};
marked.use({
extensions: [noteTokenizer, spoilerTokenizer],
renderer: customRenderer
});
С помощью этого подхода можно создавать полноценные расширения, которые добавляют новые синтаксические элементы, сохраняют совместимость с стандартным Markdown и интегрируются в существующие проекты.
parseInline внутри
рендерера для обработки вложенного Markdown.Такой подход обеспечивает гибкость и расширяемость Marked, позволяя добавлять новые элементы без изменения ядра библиотеки.