По мотивам https://github.com/bem/bem-bl/issues/313.
Предикаты в BEMHTML описываются некоторым семантическим сахаром, позволяющим, легко, но достаточно бедно выбирать узлы bemjson дерева. Более того, они имеют хоть и простой, но свой собственный синтаксис.
А ведь в web уже давно есть способ выбирать элементы дерева - CSS. Давайте попробуем описывать предикаты в BEMHTML с помощью CSS селекторов.
Новый (или дополнительный) синтаксис, я вижу таким.
block.b-test {
/* блок b-test */
}
block.b-test[modname='modval'] {
/* блок b-test с модификатором modname=modval */
}
block.b-test[attrname='val'] {
/* блок b-test с полем attrname=val */
}
block.b-test elem.item {
/* элементы item блока b-test */
}
block.b-test elem.item[modname='eq'] {
/* элементы item у которого модификатор modname=eq , блока b-test */
}
block.b-test[modname='modval'] elem.item[modname='eq'] {
/* элементы item у которого модификатор modname=eq , блока b-test, у которого модификатор modname='modval' */
}
block.b-test elem.* {
/* все элементы блока */
}
block.* {
/* все блоки */
}
Можно даже эти варианты упростить
.b-test {
/* .b-test */
}
.b-test[modname='modval'] {
/* блок b-test с модификатором modname=modval */
}
.b-test_modname_modval {
/* блок b-test с модификатором modname=modval */
}
.b-test[attrname='val'] {
/* блок b-test с полем attrname=val */
}
.b-test__item {
/* элементы item блока b-test */
}
.b-test__item_modname_eq {
/* элементы item у которого модификатор modname=eq , блока b-test */
}
CSS селекторы достаточно мощны, при этом декларативны, при этом очень многим понятны.
Более сложны варианты можно посмотреть в оригинальной ветке обсуждения.
Как вам такой вариант записи?
Шикарно! Собственно напрашевается -- спасибо, Кэп.
.b-test__item_modname_eq — на мой взгляд единственный правильный вариант, если уж сокращать.
Добавь сюда же примеры с кастомными js подпредикатами и режимы (моды)
А если у меня классы my-block--elem_mode?
Как ты объяснишь, что можно написать
но при этом нельзя
?
Ещё интересно, как будет выглядеть аналог такого кода:
block b-block {
elem {
// ...
}
}
block.b-test[modname='modval'] elem.item2
или block.b-test[modname='modval'] elem.[name^="item"]
Не про то вопрос. Ты ведь знаешь, почему нельзя посмотреть вглубь? Так что с CSS-подобным синтаксисом это неочевидно.
__elem или &__elem или elem.elem {
// ...
}
}
b-test__item_modname_eq - с первого взгляда только такая запись смотрится немного выигрышнее;
block.b-menu elem.* || block.b-menu block.b-test || (this.ctx.someattr == "some") - а вот об это я поломал глаза 2 раза.
css работает с дом-деревом в терминах теги/классы/атрибуты;
bemhtml работает с бэм-деревом в терминах блоки/элементы/модификаторы/миксины и т.д;
По сути, мы имеем дело с двумя разными пересекающимися множествами, так что совсем не факт, что css будет удобнее. Меня лично bemhtml с точки зрения селекторов вполне устраивает, и на понимае их у меня ушло время равное прочтению предостовляемых бэмштмлем мод. Плюс bemhtml является языком более высокого уровня чем css, и такой переход смотриться подобно смене c++ на ассемблер.
Один раз настроить синтаксис для проекта где-то в настройках.
попробуйте выразить это с помощью того, что есть сейчас
нельзя потому что не хотим
Так нельзя, там нет понятия вложенности.
Чтобы это попробовать выразить, нужно сначала понять, что здесь написано. Я не понимаю, что здесь значит пробел и какой приоритет операций.
Здесь есть каскад?
Я совсем не понимаю, как быть с селекторами, которые про каскад.
Сделаешь прототип?
и надеюсь никогда не будет
Кто-нибудь может захотеть сделать альтернативную реализацию шаблонов, которая это будет уметь. Мы, собственно, не против. Пусть расцветают все цветы!
Предположу, что вы хотели сказать, что на псевдо-bemhtml это бы выглядело почти точно так же, и новый синтаксис ничуть не портит восприятие, например:
block b-menu elem * || block b-menu block b-test || (this.ctx.someattr == "some")
И я даже могу согласиться с таким утверждением, вот только вторая часть выражения это большое зло: как только появиться каскад в bemhtml - станет невозжно бегать и искать по исходникам какой же блок влияет на другой блок, помоему БЭМ не об этом.
Читать такой код не приятно не потому что запятые заменились пробелами, а пробелы точечками. Всё дело в том, что трактовать такой предикат сложнее, потерялась однозначность, что-ли.
И ещё, если ввести синтаксис CSS по полной, то появиться куча трешевых ситуаций, от которых вести разработку проектов станет затруднительно (как в примере выше с каскадом).
Наконец, имхо, просто чисто эстетически предикат из css-выражений смотрится хуже рядом с js-кодом.
селектор, который про каскад работает так-же как и в css.
block.b-menu block.b-test - найти все блоки b-test внутри b-menu
В BEMHTML нет каскада
Так кто захочет — тот пусть и делает. Зачем в нашей реализации учитывать это в синтаксисе?
Но тогда нельзя заимствовать чужие шаблоны. Или даже если можно заимствовать, у них будет другой синтаксис и я сломаю глаза
Тогда варианта два: либо помимо глобальных настроек дать возможность задавать их в чём-то вроде yaml-пролога, либо быть тоталитарнее и диктовать только один вариант.
Ну и я не говорю, о том, что не должно быть варианта типа elem.bar[modname="modval"], они должны быть, но должен быть и шорткат. Как и в CSS можно написать foo[class~="blah"] и это будет почти равнозначно foo.blah, но при этом здорово бы иметь шорткат, даже если он будет один.
Мы пока даже не рассматриваем такой вариант.
Я предложил Саше сделать прототип.
А чо
block.b-test и block.b-test elem.item[modname='eq'],
но не
b-test и b-test.item[modname='eq']
или
b-test и item@b-test[modname='eq']?
Просто интересно, почему надо пытаться под css подстроится.
Всё, что поможет тебе продемонстрировать мощь такого подхода и найти единомышленников для полноценной реализации.
Ты используешь синтаксис, придуманный для каскада там, где каскада нет.
Любой элемент можно выразить отдельным блоком, просто он будет бессмысленным вне этого блока, но это уровень семантики, а не технологии.
Пользователь не может воспользоваться каскадом, нельзя написать шаблон на сущность вложенную в другую сущность.
Элемент — это не каскад. Это зашито в технологию, каскада нет.
Элементы — это сущность, у которой есть свойство принадлежности к блоку. Находиться внутри она при этом не должна. Так же это реализовано на уровне кода.
Более того, если я правильно понимаю, возможен случай, когда элемент (на уровне bemjson/html) будет находиться без блока. По крайней мере текущая реализация bem-tools/bemhtml такой случай пропустит.
Скажем, когда элементы не сосредоточенны внутри какого-то враппера, а раскиданы по всей старице и никакой из них не является более главным (нельзя выразить как отдельные блоки), и при всём этом элементы друг без друга не имеют никакого смысла, поэтому их нужно выделить в один блок. Можно сказать, что враппером является b-page, и надо просто примиксовать блок к b-page, но с точки зрения вёрстки это будет излишним.
Если я ошибаюсь, поправьте меня.
Да, всё верно. Единственный момент — если требуется js-функциональность, отдельностоящий элемент придётся смешать с его же блоком. Но это лишь особенности реализации i-bem.js, в котором объект есть только у блока (у каждого элемента мы посчитали "дорого" по объекту делать).
Писать шаблонизаторы - не то, чем мне мне хотелось бы заниматься.
Я предложил синтаксис, который мне, как верстальщику, был бы удобен и, возможно, помог бы уменьшить порог входа в стек БЭМ технологий другим верстальщикам.
Нет! Текущий синтаксис прекрасен. Нахрена вам сдались эти точки с подчеркиваниями? Советую автору пойти читать внимательнее бумагу