Создание Rehype-плагина для корректировки HTML-кода при конвертировании из Markdown
Простейший код конвертирования 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>