Created
October 5, 2017 17:36
-
-
Save qfox/bb5720e20b9d8b3ac95ff950a4cb7ead to your computer and use it in GitHub Desktop.
ffs.deps.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Узел содержит значение с маской и связи. Формат узла: | |
{ | |
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 | |
в порядке от узла к корню. При выходе за границы узла используем | |
родительский контекст. | |
{block: 'b', elems: 'e'} → [{block: 'b'}, {block: 'b', elem: 'e'}] | |
{scope: {block: 'b'}, elems: 'e'} → [{block: 'b', elem: 'e'}] | |
{scope: {block: 'b', elem: 'e'}, mods: {a: 1}} | |
→ [{block: 'b', elem: 'e', modName: 'a', modVal: '1'}] | |
{scope: {block: 'b', elem: 'e'}, block: 'b', mods: {a: 1}} → | |
[{block: 'b'}, {block: 'b', elem: 'e', mod: 'a', val: '1'}] | |
{scope: {block: 'b'}, mods: {a: 1}, elems: [{elem: 'e', mods: {a: 1}}]} → | |
Хочу только модификаторы блока и элементов | |
{scope: 'b', mods: {a: 1}, elems: [{scope: 'e', mods: {a: 1}}]} → | |
Хочу только модификаторы элемента | |
{scope: {block: 'b', elem: 'e'}, mods: {a: 1}} | |
b__ww.deps.js | |
{scope: {block: 'b', elem: 'ww'}, elems: [{elem: 'e', mods: {a: 1}}]} | |
{elems: [{elem: 'e', mods: {a: 1}}]} | |
{elems: 'e', mods: {m: ['v']}} → [{elem: 'e'}, {elem: 'e', modName: 'm', modVal: 'v'}] | |
{scope: {mod: 'm'}, vals: ['a', 'b', 'c']} | |
{elems: ['asd', 'zxc']} → [{elem: 'asd'}, {elem: 'zxc'}] | |
b.deps.js | |
({ | |
block: 'c', | |
shouldDeps: {block: 'c', elems: ['a', 'b']} | |
}); | |
({ | |
shouldDeps: {elems: ['a', 'b']} | |
}); | |
{ | |
block: 'b', | |
elem: undefined, | |
mod: 'a', | |
val: 'b', | |
elems: [ | |
{ | |
elem: 'e', | |
mods: { | |
m: ['v', 'v2'], | |
m2: ['v', 'v2'] | |
} | |
}, | |
'e2', | |
'e3' | |
] | |
} | |
b_m.deps.js | |
b_m_v.deps.js | |
c_theme.deps.js: | |
{ shouldDeps: [{val: 'islands'}, {val: 'normal'}] } | |
c_theme_islands | |
c_theme_normal | |
c.deps.js | |
{ shouldDeps: {mod: 'theme', val: true}} | |
[ | |
{block: 'b'}, | |
{block: 'b', elem: ['e', 'e2'], mods: {a: 1}}, — запретить | |
{block: 'b', elem: 'e', mods: {a: 1}}, — норм | |
{block: 'b', elem: ['e', 'e2']}, — норм | |
{block: 'b', mods: {a: 1}}, — норм | |
{block: 'b', elem: 'e2'}, | |
{block: 'b', elem: 'e3'}, | |
{block: 'b', mod: 'm', val: 'v'}, | |
{block: 'b', mod: 'm', val: 'v2'}, | |
{block: 'b', mod: 'm2', val: 'v'}, | |
{block: 'b', mod: 'm2', val: 'v2'}, | |
{block: 'b', elem: 'e', mod: 'm', val: 'v'}, | |
{block: 'b', elem: 'e', mod: 'm', val: 'v2'}, | |
{block: 'b', elem: 'e', mod: 'm2', val: 'v'}, | |
{block: 'b', elem: 'e', mod: 'm2', val: 'v2'} | |
] | |
## Общий алгоритм | |
- построение графа | |
- 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 в массивы, для каждого нестрокового элемента массива повторяем. | |
- Делаем из дерева неупорядоченный плоский список | |
- Нормализуем синтаксис узлов в полную форму (`{block: ?String, elem: ?ElemEntity[], elems: ?ElemEntity[], mod: ?String, val: ?String, mods: ?Object})` — результатом является дерево нормализованных масок. | |
- Раскрываем маски тенорков (`[{block: ?String, elem: ?String, modName: ?String, modVal: ?String}]`) — получаем дерево массивов тенорков *3. | |
- Перестраиваем дерево путем разделения массивов тенорков в узле на отдельные узлы с сохранением зависимостей (shouldDeps, mustDeps). Декартово произведение массива тенорков на массивы зависимостей. | |
- Используя контекст файла в качестве корневого, рекурскивно наполняем каждый узел контекстом: | |
- На вход получаем родительский и текущий узлы. | |
- Наполняем поле tech, если его нет в узле, но есть в родителе. | |
- Проверяем в узле поле block — значит узел полный, выходим, иначе — наполняем поле block в узле. | |
- Проверяем в узле поле elem, если есть — выходим, иначе — наполняем поле elem в узле. | |
- Формируем список зависимостей в итоговом формате. Добавляем зависимость для каждого узла (тенорка) в результирующий плоский список связей между тенорками. | |
**NB:** ФОЗ (файл описания зависимостей) — сущность файловой системы (файл или папка), содержащая информацию о зависимостях. | |
**NB:** Рекурсивную нормализованную структуру ФОЗ можно описать следующим образом: | |
```js | |
DepsCollection = Array<DepsItem> | |
DepsItem = { | |
tech: ?String, | |
block: ?String, | |
elem: ?String, | |
modName: ?String, | |
modVal: ?String, | |
shouldDeps: ?DepsCollection, | |
mustDeps: ?DepsCollection | |
} | |
``` | |
**NB:** noDeps RIP. | |
**NB:** *3 Раскрытие масок на ваше усмотрение. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment