Простейший код конвертирования Markdown-разметки в HTML-код при помощи библиотек Remark/Rehype выглядит примерно так:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const getHtml = async (markdown) => {
const vfile = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify)
.process(markdown);
return vfile.value;
};
Для того, чтобы изменить генерируемый HTML-код, например, добавить к некоторым элементам классы, атрибуты или обернуть их в другие элементы, необходимо вклиниться в процесс конвертирования при помощи дополнительных плагинов.
В инфраструктуре Remark/Rehype можно найти плагин почти на любой случай. Тем не менее, в этом предложении ключевое слово "почти". В моей практике нередко приходилось сталкиваться с ситуацией, когда я не мог найти подходящий плагин. В этом случае можно создать собственный плагин, который будет выполнять ровно то, что необходимо.
Далее я покажу пример создания простого Rehype-плагина, который оборачивает все элементы img
в дополнительный элемент a
, для того, чтобы разметка соответствовала требованиям для подключения популярной библиотеки fslightbox
, раскрывающей изображения на весь экран.
import { unified } from 'unified';
import { visit } from 'unist-util-visit';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const rehypeImages = () => {
return (tree) => {
visit(tree, 'element', (node, index, parent) => {
if (node.tagName === 'img') {
node.properties.className = ['rounded-md'];
parent.children[index] = {
type: 'element',
tagName: 'a',
properties: { href: node.properties.src, 'data-fslightbox': '' },
children: [node]
};
}
});
};
};
const getHtml = async (markdown) => {
const vfile = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeImages)
.use(rehypeStringify)
.process(markdown);
return vfile.value;
};
Таким образом, все элементы img
в HTML-коде, которые выглядели так:
<img src="image.png" alt="description" />
после подключения плагина будут такими:
<a href="image.png" data-fslightbox="">
<img src="image.png" class="rounded-md" alt="description" />
</a>
Рабочий пример этого решения можно посмотреть здесь.