При работе с Markdown через Remark и последующей
обработке HTML через Rehype ключевым аспектом является
управление изображениями. В стандартном Markdown синтаксисе изображения
определяются через . При трансформации
через Remark и Rehype можно внедрять дополнительные атрибуты,
необходимые для современных веб-приложений: loading="lazy",
srcset, sizes и alt.
Remark преобразует Markdown в AST (Abstract Syntax
Tree), где каждая сущность документа представлена узлом. Узел
типа image имеет следующие свойства:
{
type: 'image',
title: 'Название изображения',
url: '/images/picture.jpg',
alt: 'Описание изображения'
}
Эти свойства можно использовать для генерации оптимизированного HTML с поддержкой lazy loading и responsive images.
Lazy loading — это отложенная загрузка изображений, когда они появляются в области видимости пользователя. В HTML это реализуется атрибутом:
<img src="/images/picture.jpg" loading="lazy" alt="Описание изображения">
Для интеграции в Remark/Rehype можно использовать плагин
Rehype, который обходит все узлы типа image и
добавляет атрибут loading="lazy":
const rehypeLazyImages = () => {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'img') {
node.properties = node.properties || {};
node.properties.loading = 'lazy';
}
});
};
};
В этом коде:
visit — функция из библиотеки
unist-util-visit для обхода дерева.tagName === 'img' получают атрибут
loading.srcset и sizesДля адаптивной загрузки изображений браузеры используют атрибуты
srcset и sizes. Пример структуры:
<img
src="/images/picture-800.jpg"
srcset="/images/picture-400.jpg 400w, /images/picture-800.jpg 800w, /images/picture-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px"
alt="Описание изображения"
loading="lazy">
В Remark можно создавать плагин для генерации srcset на
основе определённого правила именования файлов:
const rehypeResponsiveImages = () => {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'img') {
const baseUrl = node.properties.src.replace(/\.\w+$/, '');
const ext = node.properties.src.match(/\.\w+$/)[0];
const srcset = [400, 800, 1200]
.map(width => `${baseUrl}-${width}${ext} ${width}w`)
.join(', ');
node.properties.srcset = srcset;
node.properties.sizes = '(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px';
}
});
};
};
Этот плагин автоматически генерирует набор изображений разных размеров, позволяя браузеру выбирать оптимальное изображение для текущего экрана.
Для полноценной оптимизации изображения можно объединить оба подхода:
const rehypeOptimizeImages = () => {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'img') {
const baseUrl = node.properties.src.replace(/\.\w+$/, '');
const ext = node.properties.src.match(/\.\w+$/)[0];
node.properties.loading = 'lazy';
node.properties.srcset = [400, 800, 1200]
.map(width => `${baseUrl}-${width}${ext} ${width}w`)
.join(', ');
node.properties.sizes = '(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px';
}
});
};
};
При обработке Markdown через Remark важно помнить:
<img>. Плагин Rehype должен корректно
работать с обоими вариантами.srcset и
sizes.import { remark } from 'remark';
import remarkHtml from 'remark-html';
import { rehype } from 'rehype';
import rehypeRaw from 'rehype-raw';
import { visit } from 'unist-util-visit';
remark()
.use(remarkHtml)
.process('# Заголовок\n')
.then((file) => {
rehype()
.data('settings', { fragment: true })
.use(rehypeRaw)
.use(rehypeOptimizeImages)
.process(file.toString())
.then((html) => {
console.log(String(html));
});
});
Эта цепочка демонстрирует:
<img> для
добавления lazy loading и responsive атрибутов.srcset снижает загрузку ненужных ресурсов на мобильных
устройствах.В результате интеграция Remark и Rehype с оптимизацией изображений позволяет создавать современные, быстрые и адаптивные веб-страницы, сохраняя при этом гибкость Markdown и удобство AST-обработки.