Строчные элементы (inline elements) — это элементы, которые располагаются внутри блочных элементов и не создают новых блоков разметки. В контексте работы с Markdown через библиотеку Remark и его HTML-парсер Rehype понимание структуры и обработки строчных элементов критично для точного преобразования и модификации контента.
В Markdown и соответствующих AST (Abstract Syntax Tree) структурах Remark выделяются следующие ключевые строчные элементы:
Text (text) Наиболее простой тип
узла, содержащий текст без форматирования.
{ type: 'text', value: 'Пример текста' }Emphasis (emphasis) Представляет
курсивное выделение текста, создается с помощью * или
_.
{
type: 'emphasis',
children: [{ type: 'text', value: 'курсив' }]
}Strong (strong) Жирное выделение
текста через ** или __.
{
type: 'strong',
children: [{ type: 'text', value: 'жирный текст' }]
}InlineCode (inlineCode) Код внутри
строки, обрамленный обратными кавычками `.
{ type: 'inlineCode', value: 'console.log("Hello")' }Link (link) Гиперссылки с текстом и
URL.
{
type: 'link',
url: 'https://example.com',
title: 'Пример',
children: [{ type: 'text', value: 'Перейти на сайт' }]
}Image (image) Встраиваемое
изображение с альтернативным текстом и URL.
{
type: 'image',
url: 'https://example.com/image.png',
alt: 'Описание изображения'
}Break (break) Принудительный
перенос строки. В AST представлен узлом типа
break.
AST в Remark строится иерархически: блочные элементы содержат массив
children, внутри которого находятся строчные узлы. Пример
для параграфа:
{
type: 'paragraph',
children: [
{ type: 'text', value: 'Это пример ' },
{ type: 'strong', children: [{ type: 'text', value: 'жирного текста' }] },
{ type: 'text', value: ' и ' },
{ type: 'emphasis', children: [{ type: 'text', value: 'курсива' }] },
{ type: 'text', value: '.' }
]
}
Каждый строчный элемент может содержать другие строчные элементы в качестве дочерних узлов. Это позволяет строить сложные структуры текста: ссылки внутри жирного текста, код внутри курсивного выделения и т. д.
Rehype используется для конвертации Markdown AST в HTML AST или для обхода HTML-структуры. Строчные элементы требуют внимательного маппинга:
| Remark Type | Rehype Element | Примечание |
|---|---|---|
text |
#text |
Прямое отображение текста |
emphasis |
em |
Оборачивает дочерние узлы в тег <em> |
strong |
strong |
Оборачивает дочерние узлы в тег <strong> |
inlineCode |
code |
Тег <code> без блока |
link |
a |
Атрибуты href и title передаются из
AST |
image |
img |
Атрибуты src и alt передаются
напрямую |
Remark предоставляет возможность создавать плагины для обработки и модификации AST. Для строчных элементов часто используют следующие подходы:
Поиск и замена текста Обход всех
text узлов и изменение их значения.
function remarkReplaceText() {
return (tree) => {
visit(tree, 'text', (node) => {
node.value = node.value.replace(/важно/g, 'ВАЖНО');
});
};
}Оборачивание узлов в теги Пример: все слова
важно оборачиваются в strong.
function remarkWrapImportant() {
return (tree) => {
visit(tree, 'text', (node, index, parent) => {
if (node.value.includes('важно')) {
const parts = node.value.split(/(важно)/);
const newNodes = parts.map((part) =>
part === 'важно'
? { type: 'strong', children: [{ type: 'text', value: part }] }
: { type: 'text', value: part }
);
parent.children.splice(index, 1, ...newNodes);
}
});
};
}Конвертация в HTML После обработки AST с помощью
плагинов можно использовать rehype для генерации HTML с
корректными тегами для строчных элементов.
Вложенность Все строчные элементы поддерживают рекурсивную вложенность, что важно учитывать при обходе AST.
Порядок обхода Порядок обхода узлов может влиять
на результаты обработки, особенно при модификации текста внутри
strong и emphasis.
Сочетание с блочными элементами Понимание того, что строчные элементы существуют внутри блочных элементов, помогает правильно строить плагины и трансформации Markdown в HTML.
Сохранение исходной структуры При любых модификациях следует соблюдать типы узлов и вложенность, чтобы не сломать рендеринг в HTML.
Пример плагина для Remark + Rehype, который:
JavaScript.<strong>.import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import { visit } from 'unist-util-visit';
function wrapJavaScript() {
return (tree) => {
visit(tree, 'text', (node, index, parent) => {
if (node.value.includes('JavaScript')) {
const parts = node.value.split(/(JavaScript)/);
const newNodes = parts.map((part) =>
part === 'JavaScript'
? { type: 'strong', children: [{ type: 'text', value: part }] }
: { type: 'text', value: part }
);
parent.children.splice(index, 1, ...newNodes);
}
});
};
}
const processor = unified()
.use(remarkParse)
.use(wrapJavaScript)
.use(remarkRehype)
.use(rehypeStringify);
const markdown = 'Я изучаю JavaScript и хочу стать экспертом.';
processor.process(markdown).then((file) => console.log(String(file)));
Результат генерации HTML:
<p>Я изучаю <strong>JavaScript</strong> и хочу стать экспертом.</p>
Строчные элементы являются основой точного и гибкого преобразования Markdown в HTML через Remark и Rehype. Их правильное понимание позволяет создавать сложные плагины, управлять форматированием текста и строить надежные конвейеры обработки контента.