Skip to content
Alexey Yaroshevich edited this page Sep 6, 2016 · 9 revisions

Общий алгоритм

  • построение графа
    • walkerом составляем список всех файлов
      • передаем настройки уровней со схемами именования/вложенности (bem-config) и набор уровней для прохода (массив строк)
      • получаем неупорядоченный поток объектов, описывающий файл и тенорок, к которому он относится: {level: String, path: String, entity: BemEntityName, tech: String}
      • схемы содержат алгоритм обхода уровня и влияют на то, какие файлы вернутся
    • из общего потока файлов оставляем только файлы описания зависимостей (далее ФОЗ)
    • из каждого ФОЗ получаем нормализованный список зависимостей
      • чтение и нормализация ФОЗ происходит с помощью обработчика для нужного формата
      • итоговый формат: Array<{vertex: {entity, tech}, dependOn: {entity, tech}, ordered}>
    • строим граф по всем полученным связям между сущностями используя bem-graph
  • работаем с графом
    • получаем упорядоченный набор «тенорков» для сборки по декларации и технологии для сборки бандлов
    • по нему получаем упорядоченный набор файлов сортированный в соответствии с уровнями переопределения
    • передаем всё в руки пользователя

Обработчик формата new-deps.js

  • Читаем и эвалим файл в JS-объект в формате deps.js
  • Валидируем формат (можно отключить)
  • Нормализуем синтаксис (приводим к формату DepsCollection)
    • Нормализуем в структуру дерева
      • Заворачиваем содержимое файлов в корневой узел {shouldDeps: …}
      • Нормализуем структуру связей для каждого узла, начиная с корневого: трансформируем единичные значения shouldDeps/mustDeps в массивы, для каждого нестрокового элемента массива повторяем.
  • Делаем из дерева неупорядоченный плоский список
    • При обходе дерева заходом в shouldDeps и mustDeps узла и каждого элемента в поле elems.
    • Нормализуем синтаксис узлов в полную форму (см. *3) — результатом является дерево нормализованных масок.
    • Раскрываем маски тенорков (Array<{block: ?String, elem: ?String, modName: ?String, modVal: ?String}>) для каждого узла и каждого его элемента — получаем дерево массивов тенорков ({entities: Array<BemEntity>, elems: ?Array<{entities: Array<BemEntity>, shouldDeps: ?*, mustDeps: ?*}>, shouldDeps: ?*, mustDeps: ?*}).
    • Перестраиваем дерево путем разделения массивов тенорков в узле на отдельные узлы с сохранением зависимостей; shouldDeps и mustDeps относятся к БЭМ-сущности узла, в котором находятся. Декартово произведение массива тенорков на массивы зависимостей.
    • Используя контекст файла в качестве корневого, рекурскивно наполняем каждый узел контекстом:
      • На вход получаем родительский и текущий узлы.
      • Наполняем поле tech, если его нет в узле, но есть в родителе.
      • Проверяем в узле поле block — значит узел полный, выходим, иначе — наполняем поле block в узле.
      • Проверяем в узле поле elem, если есть — выходим, иначе — наполняем поле elem в узле.
  • Формируем список зависимостей в итоговом формате. Добавляем зависимость для каждого узла (тенорка) в результирующий плоский список связей между тенорками.

NB: ФОЗ (файл описания зависимостей) — сущность файловой системы (файл или папка), содержащая информацию о зависимостях.

NB: Рекурсивную нормализованную структуру ФОЗ можно описать следующим образом:

DepsCollection = Array<DepsItem>
DepsItem = {
  tech: ?String,
  block: ?String,
  elem: ?String,
  modName: ?String,
  modVal: ?String,
  shouldDeps: ?DepsCollection,
  mustDeps: ?DepsCollection
}

NB: noDeps RIP.

NB: *3 Раскрытие масок предлагается таким:

// Узел содержит значение с маской и связи. Формат узла:
{
  scope: {block: ?String, elem: ?String},
  block: ?String,
  elems: ?Array<{
    scope: {block: ?String, elem: ?String},
    elem: ?String,
    mods: ?Object<String, String[]>,
    shouldDeps: ?Array,
    mustDeps: ?Array
  }>,
  mods: ?Object<String, String[]>,
  shouldDeps: ?Array,
  mustDeps: ?Array
};

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

Clone this wiki locally