Комментарии и doctype

Комментарии в Remark

Remark — это универсальный парсер Markdown в экосистеме JavaScript, который строит абстрактное синтаксическое дерево (AST) на основе исходного текста. Одной из ключевых возможностей при обработке Markdown является поддержка комментариев. В Remark комментарии представлены в виде узлов типа html, поскольку Markdown сам по себе не имеет нативного синтаксиса для комментариев, но допускает вставку HTML-кода.

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';

const markdown = `
# Заголовок

<!-- Это комментарий -->

Текст после комментария
`;

const processor = unified()
  .use(remarkParse)
  .use(remarkStringify);

const file = processor.processSync(markdown);
console.log(String(file));
  • Тип узла: html
  • Содержимое: весь HTML-код между тегами, включая комментарии <!-- -->.
  • Использование: можно фильтровать или модифицировать комментарии с помощью плагинов, анализируя AST.
Фильтрация комментариев

Для удаления всех комментариев из Markdown можно использовать функцию-плагин:

function removeComments() {
  return (tree) => {
    visit(tree, 'html', (node, index, parent) => {
      if (node.value.startsWith('<!--')) {
        parent.children.splice(index, 1);
        return [visit.SKIP, index];
      }
    });
  };
}

Функция visit импортируется из unist-util-visit и позволяет обходить дерево узлов. Данный метод обеспечивает безопасное удаление комментариев без нарушения структуры документа.

Комментарии в Rehype

Rehype работает с HTML AST (hast) и позволяет оперировать комментариями напрямую. В HAST комментарии представлены отдельным узлом с типом comment:

import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';

const html = `
<!DOCTYPE html>
<html>
<body>
<!-- Комментарий в HTML -->
<p>Пример текста</p>
</body>
</html>
`;

const processor = unified()
  .use(rehypeParse, { fragment: false })
  .use(rehypeStringify);

const file = processor.processSync(html);
console.log(String(file));
  • Тип узла: comment
  • Доступ к содержимому: node.value
  • Обход и модификация: аналогично Remark, но с узлами hast.
Извлечение комментариев

Для анализа или модификации HTML-комментариев удобно использовать unist-util-visit:

import { visit } from 'unist-util-visit';

visit(tree, 'comment', (node) => {
  console.log(node.value); // выводит текст комментария
});

Работа с DOCTYPE

DOCTYPE в HTML обозначает тип документа и обычно располагается в начале файла. Rehype корректно обрабатывает DOCTYPE как отдельный узел с типом doctype:

visit(tree, 'doctype', (node) => {
  console.log(node.name); // например, "html"
});
  • Особенности:

    • DOCTYPE всегда верхнего уровня, вне <html>
    • Может содержать публичные или системные идентификаторы (например, для XHTML)
    • Для модификации можно менять node.name или добавлять дополнительные параметры через node.public и node.system.
Создание DOCTYPE программно
const tree = {
  type: 'root',
  children: [
    { type: 'doctype', name: 'html' },
    { type: 'element', tagName: 'html', children: [] }
  ]
};

Это полезно при генерации HTML с нуля через Rehype.

Совместное использование Remark и Rehype

Remark и Rehype часто используют совместно через плагин remark-rehype, что позволяет конвертировать Markdown в HTML с сохранением комментариев и DOCTYPE:

import remarkRehype from 'remark-rehype';

unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeStringify)
  .processSync(markdown);
  • Комментарии в Markdown превращаются в узлы типа comment в HAST.
  • DOCTYPE можно добавить после конверсии, чтобы сформировать корректный HTML-документ.

Рекомендации по обработке

  • Всегда различать типы узлов: html в Remark и comment в Rehype.
  • Для массовой модификации использовать обход дерева (visit) вместо строкового поиска.
  • DOCTYPE рекомендуется добавлять на финальной стадии генерации HTML, чтобы избежать конфликтов с другими элементами документа.

Эти подходы обеспечивают гибкую работу с комментариями и DOCTYPE в экосистеме Remark/Rehype, поддерживая чистоту структуры AST и позволяя создавать динамически модифицируемый HTML-контент.