Свойства и их нормализация

В экосистеме Remark и Rehype свойства узлов (nodes) играют ключевую роль при обработке и трансформации AST (Abstract Syntax Tree). Каждый узел в дереве имеет базовую структуру, включающую type, опциональные children и набор свойств, которые задают конкретные параметры элемента. Правильная работа с этими свойствами требует понимания их типов, особенностей нормализации и взаимодействия с плагинами.


Типы свойств

Свойства узлов можно разделить на несколько категорий:

  1. Атрибуты HTML или Markdown Для Rehype узлы HTML-элементов содержат свойства, соответствующие стандартным атрибутам: id, className, src, href и т.д. Remark работает с Markdown-специфичными свойствами, например, ordered для нумерованных списков или depth для заголовков.

  2. Метаданные узлов Сюда входят поля, необходимые для обработки узла внутри AST: position, data, lang. Поле position содержит объект с информацией о местоположении узла в исходном тексте (start, end), что позволяет корректно отображать ошибки или проводить трансформации.

  3. Служебные поля плагинов Плагины Remark и Rehype могут добавлять собственные свойства к узлам, например, hProperties для Rehype, где хранятся атрибуты, специфичные для обработки HTML. Эти свойства обычно нормализуются для единообразного взаимодействия с плагинами.


Нормализация свойств

Нормализация свойств — процесс приведения их к единому формату, который гарантирует корректную обработку и совместимость с плагинами и выходными форматами. Основные принципы:

  1. Ключи и регистр Атрибуты HTML должны быть приведены к нижнему регистру (classNameclass), чтобы соответствовать стандарту HTML. Remark нормализует ключи Markdown-атрибутов по внутренним соглашениям (ordered всегда булево).

  2. Массивы и строки Некоторые свойства могут быть заданы как массив или строка. Например, className в Rehype допускает запись как "foo bar" или ["foo", "bar"]. Нормализация приводит все к массиву для удобства дальнейшей обработки.

  3. Булевы значения Свойства типа checked (для чекбоксов) или ordered (для списков) нормализуются к булевым значениям, даже если исходный синтаксис допускает альтернативные формы (null, undefined, "true").

  4. Удаление пустых свойств Для снижения объема AST и предотвращения ошибок рендеринга свойства с null или пустыми строками могут быть удалены при нормализации.


Взаимодействие с AST

При обходе AST и трансформации узлов нормализованные свойства обеспечивают стабильную работу:

  • Безопасная генерация HTML Rehype при преобразовании AST в HTML ориентируется на нормализованные свойства, что исключает дублирование атрибутов и некорректные значения.

  • Плагинная совместимость Плагины могут быть уверены в типах и формате свойств, что упрощает фильтрацию и модификацию узлов.

  • Унификация Markdown-расширений Remark использует нормализацию для того, чтобы расширения, добавляющие собственные свойства к узлам (например, таблицы, footnotes), корректно работали с другими плагинами и парсерами.


Практические примеры нормализации

  1. Нормализация класса элемента в Rehype:
import {visit} from 'unist-util-visit';

function normalizeClasses(tree) {
  visit(tree, 'element', node => {
    if (node.properties?.className) {
      if (typeof node.properties.className === 'string') {
        node.properties.className = node.properties.className.split(/\s+/);
      }
    } else {
      node.properties = {...node.properties, className: []};
    }
  });
}
  1. Булевы свойства в Remark:
import {visit} from 'unist-util-visit';

function normalizeCheckbox(tree) {
  visit(tree, 'listItem', node => {
    if (node.checked !== undefined) {
      node.checked = Boolean(node.checked);
    }
  });
}
  1. Удаление пустых свойств:
function removeEmptyProps(tree) {
  visit(tree, node => {
    for (const key in node) {
      if (node[key] === null || node[key] === '') {
        delete node[key];
      }
    }
  });
}

Особенности обработки нестандартных свойств

  • hProperties и hChildren В Rehype часто используются специальные поля hProperties (для атрибутов) и hChildren (для дочерних узлов HTML). Их нормализация включает проверку типов и приведение к массиву для консистентности.

  • data-поле для Remark Плагины могут записывать свои данные в node.data. Нормализация предполагает хранение структурированных объектов и исключение примитивов, которые могут конфликтовать с внутренней обработкой.

  • Сериализация и десериализация Нормализованные свойства позволяют безопасно конвертировать AST в JSON и обратно без потери типов и структуры данных.


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

  • Всегда проверять типы и корректность свойств перед трансформацией AST.
  • Использовать единый формат массивов для атрибутов, чтобы плагины могли объединять и фильтровать классы и другие списочные значения.
  • Удалять пустые или null свойства перед рендерингом, чтобы избежать лишнего мусора в HTML.
  • Сохранять пользовательские данные в data вместо добавления нестандартных полей в корень узла.

Нормализация свойств в Remark и Rehype не просто упрощает работу с AST, она обеспечивает консистентность, предсказуемость и совместимость с экосистемой плагинов, что особенно важно при масштабных проектах и автоматической генерации контента.