bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

Problems? POBEMS! PostCSS плагин для BEM #1061

Open belozer opened 8 years ago

belozer commented 8 years ago

Всем привет. Благодаря репозиторию @tadatuta наткнулся на интересный плагин к PostCSS - rebem-css. Изначально показался он показался менее удобным, чем написание по-старинке.

// по-старинке
.object-item
  &_status_bad
    .object-item__extended
      background: #000

// rebem-css
:block(object-item)
  &:mod(status bad)
    :block(object-item):elem(extended)
      background: #000

Проблема 1

Подсветка синтаксиса при таком написание режет глаза...

Проблема 2

Код становится ещё длиннее... Утешает только то, что можно применять bem-naming

Проблема 3

Писали, что такой синтаксис ближе к BEMHTML. Но как по мне, он не дотягивает немного.

В итоге я решил сделать PR. В репозиторий rebem/css, переписав практически весь плагин. Но т.к. на слитие нужно время, а мне он нужен уже сейчас, был сделан новый плагин с расширенным функционалом на основе rebem-css.

POBEMS поддерживает как синтаксис rebem-css, так и свой.

Решение 1-й проблемы

Добавлена возможность написания через кавычки

:block('object-item')

Решение 2-й проблемы

Добавлен контекст блока при объявлениях элементов и модификаторов. Теперь можно писать так

:block('block')
  &:mod('mod val')

    :elem('elem1')
      background: #000

    :elem('elem2'):mod('mod val')
      width: 10px

      :elem('elem3')

.block_mod_val .block__elem1 
.block_mod_val .block__elem2_mod_val .block__elem3

Решение 3-й проблемы

Для объявления модификаторов добавил более привычный синтаксис через запятую :mod('mod', 'value')

:block('block')
  &:mod('mod' -> 'val')

    :elem('elem1')
      background: #000

    :elem('elem2'):mod('mod' -> 'val'):mod('mod2' -> 'val2')
      width: 10px

.block_mod_val .block__elem1 
.block_mod_val .block__elem2_mod_val.block__elem2_mod2_val2

Или в LESS стиле

:block('block') {
    &:mod('mod', 'val') {
        :elem('elem1') { }
        :elem('elem2'):mod('mod', 'val'):mod('mod2', 'val2') {}
    }
}

Что дальше...

Далее часть изменений отправлю в репозиторий rebem/css, а в pobems буду добавлять более "горячие" нововведения. Репозиторий POBEMS

vithar commented 8 years ago

А вы правда у себя в проектах используете стили на теги? А посчитайте селекторы с тегами?

Есть немножко: https://github.com/bem-site/bem.info/blob/master/blocks/common/article/article.css

Но очень хочется перейти на нормальный процессор markdown, который генерирует не html, а json и генерировать html самому. Тогда и классы по БЭМ будут.

vithar commented 8 years ago

@tadatuta https://github.com/bem/bem-forum-content-ru/issues/1061#issuecomment-232615547 — красиво же!

adinvadim commented 8 years ago

стоит ли добавлять в него short-syntax?

Я думаю стоит добавить пользовательское наименование block, elem, modifier, как сделано в https://www.npmjs.com/package/postcss-bem

Если пользователю нужно, он поставит b,e,m

belozer commented 8 years ago

Пользовательский naming может как-то так выглядеть herak('block') {} :santa:

tadatuta commented 8 years ago

@vithar

1061 (comment) — красиво же!

Я здесь готов пожертвовать красотой в пользу очевидности. Сейчас тот факт, что это селекторы на теги, а не на блоки знает только тот, кто сначала посмотрит на конфиг сборки, вникнет в конфиг postCSS, разберется как работают используемые плагины и только тогда поймет, в чем дело.

:block(b1) не так красиво, но снимает любую неоднозначность.

apsavin commented 8 years ago

@tadatuta @vithar @belozyorcev Простите, что вмешиваюсь. Я, может быть, старею, но мне кажется, что

.block__elem_mod-name_mod-val {
    prop: value;
}

Снимает любую неоднозначность и легко ищется по файлам. Имеет нулевой порог вхождения.

Да, не получится сгенерировать css в стиле Гарри Робертса. Это минус. Но если сильно захотеть - можно и заменить разделители.

tadatuta commented 8 years ago

@apsavin Я почти с тобой согласен, но есть достаточно важный кейс, когда абстракция над неймингом необходима: если есть библиотека l1 от разработчика, который использует стиль с двумя минусами и библиотека l2 от разработчика, который использует подчеркивание, то они не смогут использовать библиотеки друг друга (вариант с однократной заменой не рассматриваю, т.к. считаем, что библиотеки будут развиваться и нужно будет регулярно подтягивать апдейты).

Ну и моя лень в принципе позволяет мне пожертвовать удобством поиска по селекторам вида .my-block__my-elem_m1_v1 в пользу поиска сначала по my-block и в найденном по my-elemради возможности вместо

.my-block {
   // ...
}

.my-block__my-elem {
    // ...
}

.my-block__my-elem_m1_v1 {
   // ...
}

писать

.my-block {
    // ...

    &__my-elem {
        // ...

        &_m1_v1 {
            // ...
        }
    }
}

Особенно нестинг радует, когда начитаются MQ или нужно переименовать b1 в b2.

belozer commented 8 years ago

@apsavin я делал его, чтобы избавиться от дублирования в nested стиле когда пишешь.

// по-старинке
.object-item
  &_status_bad
    .object-item__extended
      background: #000

// rebem-css
:block(object-item)
  &:mod(status bad)
    :block(object-item):elem(extended)
      background: #000

По аналогии с разговорным языком, чтобы не говорить так: У блока object-item с модификатором status и значением bad. Элемент extended блока object-item имеет черный фон.

А говорить вот так: У блока object-item с модификатором status и значением bad. Элемент extended имеет черный фон.

И по поводу поиска:

$ grep "block('user-card')" *bloc*/**/* -r
desktop.blocks/user-card/user-card.styl::block('user-card') {
desktop.blocks/user-card/user-card.bemtree.js:block('user-card').content()((node, ctx) => {
desktop.blocks/user-card/user-card.bemtree.js:block('user-card').content()((node, ctx) => {
desktop.blocks/user-card/user-card.styl::block('user-card') {

upd. или так

$ egrep "block.*'user-card'" *block*/** -r
desktop.blocks/content/content.deps.js:    { block: 'user-card' }
desktop.blocks/content/_handler/content_handler_staff-cards.bemtree.js:    person.block = 'user-card'
desktop.blocks/user-card/user-card.styl::block('user-card') {
desktop.blocks/user-card/user-card.bemtree.js:block('user-card').content()((node, ctx) => {
belozer commented 8 years ago

что-то навеяло на такой вариант (немного схож с postcss-bem)

block: item {
  mod: visible true { // для булевых модификторов true обязательно
    elem: list {

    }
  }
  elem: photo {
    mod: size s { // а так должно именть 2 значения

    }
  }
}
belozer commented 8 years ago

Ну или даже так. BEM clean syntax

block checkbox mod theme dark {
  elem box {

  }
  elem control {

  }
}
belozer commented 8 years ago

Единственно что нужно будет плагин для редактора пилить для его подсветки

a-x- commented 8 years ago

а вот это уже пройденная bemhtml история

belozer commented 8 years ago

@a-x- но возможно она css подойдёт

belozer commented 8 years ago

Версия 1.0.0 уже близится :)

  plugin
    block
      ✓ simple
      ✓ multiple blocks
      ✓ block name with double quotes
      ✓ block name with single quotes
      ✓ with pseudo classes
      ✓ with other tags
    elem
      ✓ simple
      ✓ multiple blocks elems
      ✓ block multiple short elems
    mod
      block
        ✓ block short mod
        ✓ block multiple short mods
        ✓ multiple blocks shorts mods
        ✓ multiple blocks mods with delimeter "-" in value
        ✓ block mod
        ✓ block mod with double quotes
        ✓ block mod with single quotes
        ✓ multiple blocks mods
        ✓ mod val with delimeter "->"
      elem
        ✓ elem short mod
        ✓ elem multiple short mods
        ✓ multiple elems short mods
        ✓ elem mod
        ✓ multiple elems mods
    custom delimeters
      ✓ mods
      ✓ elem

  25 passing (46ms)

Как и говорил, в данной версии будет следующий синтаксис

block(block) {
  elem(elem) {}
  mod(mod val) {
    width: 100px;
    mod(active) {
      elem(elem5) {}
    }
  }
  elem(elem1) {}
  elem(elem3) {}
}

block(block).elem(elem) {
  width: 10px;
  mod(mod) {
    mod(mod2) {
      mod(mod3) {}
    }
  }
}

Осталось несколько вещей.

Из изменений:

ilyar commented 6 years ago

Присоединяйтесь https://github.com/bem-contrib/pobem/issues/8#issuecomment-390669064