Войти с помощью github

Хочу начать использовать БЭМ в своём небольшом проекте. Переписывать весь html через bemhtml как-то совсем не интересно.

Существует ли какая-то более простая замена, в основе которой будут обычные html-файлы c декларациями блоков? Как-то так:

{{block('title', {text:'Hello'})}}

Есть такая структура:

desktop.blocks
    input
        __control
            input__control.bemhtml
            input__control.styl
        input.bemhtml
        input.styl
desktop.bundles
    index
        index.bemjson.js

При запуске сервера "./node_modules/.bin/bem server", генерируется файл index.bemdecl.js, но он не содержит элементы блока input, а добавляет только это:

...
    {
        "name": "input"
    }
...

Проект создавал с помощью bem-stub: bem-toos, bem-core.

make.js:

/* global MAKE:false */

// process.env.YENV = 'production';

var PATH = require('path');

require('bem-tools-autoprefixer').extendMake(MAKE);

MAKE.decl('Arch', {

    blocksLevelsRegexp: /^.+?\.blocks/,
    bundlesLevelsRegexp: /^.+?\.bundles$/

});

MAKE.decl('BundleNode', {

    getTechs: function () {
        return [
            'bemjson.js',
            'bemdecl.js',
            'deps.js',
            'stylus',
            'css',
            'bemhtml',
            'html'
        ];
    },

    getForkedTechs: function () {
        return this.__base().concat(['stylus']);
    },

    getLevelsMap: function () {
        return {
            desktop: [
                'libs/bem-core/common.blocks',
                'libs/bem-core/desktop.blocks',
                'libs/bem-grid/common.blocks',
                'common.blocks',
                'desktop.blocks'
            ]
        };
    },

    getLevels: function () {
        var resolve = PATH.resolve.bind(PATH, this.root),
            buildLevel = this.getLevelPath().split('.')[0],
            levels = this.getLevelsMap()[buildLevel] || [];

        return levels
            .map(function (path) { return resolve(path); })
            .concat(resolve(PATH.dirname(this.getNodePrefix()), 'blocks'));
    },

    'create-css-node': function (tech, bundleNode, magicNode) {
        var source = this.getBundlePath('stylus');
        if (this.ctx.arch.hasNode(source)) {
            return this.createAutoprefixerNode(tech, this.ctx.arch.getNode(source), bundleNode, magicNode);
        }
    }

});

MAKE.decl('AutoprefixerNode', {

    getPlatform: function () {
        return this.output.split('.')[0];
    },

    getBrowsers: function () {
        var platform = this.getPlatform();
        switch (platform) {
            case 'desktop':
                return [
                    'last 2 versions',
                    'ie 10',
                    'ff 24',
                    'opera 12.16'
                ];
        }

        return this.__base();
    }

});

Читаю задачу-пример из документации, вот ссылка на задачу https://ru.bem.info/technology/bemhtml/2.3.0/reference/#%D0%92%D1%8B%D0%B1%D0%BE%D1%80-%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D0%B0-%D0%B2-%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8-%D0%BE%D1%82-%D1%80%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%BE%D0%B3%D0%BE-%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%B0 не могу никак понять следующие моменты: 1) в какой моде будет применен данный шаблон, при том, что мода в нем не указана block('listitem').match(!this.inListItem)(apply({inListItem:true}))?.. 2) предположим, что все же я чего-то недопонял и все-таки шаблон из моего 1-го пункта все-таки выполнился. Все, что делает метод apply(исходя из документации) - "Конструкция apply предназначена для явного вызова процедуры выбора и выполнения шаблона, предикат которого истинен в данном контексте. Конструкция позволяет вызывать шаблоны в модифицированном контексте.". Иными словами метод apply в задаче-примере всего лишь изменит свойства текущего контекста(сугубо на время выполнения apply, после выполнения apply свойство inListItem вернется в свое начальное значение до вызова apply) и возвратит результат выполнения подходящего шаблона. Каким боком(при том, что inListItem после завершения вызова apply откатился к своему первоначальному значению) в задаче-примере пытаются заюзать inListItem в block('para').match(this.inListItem).tag()('')? 3) правильно ли я понимаю, что, если в теле шаблона я попытаюсь записать что-либо в нестандартное свойство контекста, например, вот так block('b1').content()(function(){this.HELLO = 'world'}), то после этого свойство HELLO будет доступно в контексте любого последующего обрабатываемого узла bem дерева? Либо при обработке каждого нового узла бэм дерева контекст(объект по ссылке this) пересоздается заного и, в связи с чем, поле HELLO будет отсутствовать для всех последующих обрабатываемых узлов bem дерева?

Заранее благодарю.

Например я могу использовать как this.ctx.block, так и this.block для получения имя блока.

Еще не понятная история с data, например если передать в bemhtml свойство data:

{ block: 'some-block', data: 'some-data' }

, то оно будет находится как и в this.ctx.data так и в this.data

Но если передать свойство отличное от data:

{ block: 'some-block', anotherkey: 'some-data' }

, то оно будет находится только в свойстве this.ctx.anotherkey

Следующие конструкции не работают:

block('block').elem('elem').elemMod('mod-name', 'mod-value')

block('block').elem('elem').mod('mod-name', 'mod-value')

Пример из руководства по технологии по bemhtml (http://ru.bem.info/technology/bemhtml/2.3.0/bemhtml-js-syntax/) вообще вызывает ошибку

block('b-head-logo')(elem('text').elemMod('size', 'big'))

Работает только следующая конструкция:

block('block').elem('elem').match('mod-value' == this.ctx.mods['mod-name'])

Я так понимаю это бага?

Проблема невероятно чудесная. Вот здесь https://github.com/verybigman/bem-grid/blob/8218ef38503fc224219788692e7ddcd965f6428e/common.blocks/row/row.deps.js подключаю как зависимость по технологии bemhtml блоки i-bem и row. Ожидается, что шаблон row попадет в бандл с browser.js. Но не все так просто. При запуске в браузере получаю ошибку: Uncaught Error: Module "row": can't resolve dependence "BEMHTML", тесты проходят безупречно. Почему в фантоме все ок, а в живом браузере нет? Народ, помогите, я спать не могу из-за этого. Сбросить кэш не предлагать. Подключать bemhtml.js тоже не true. Сборщик bem-tools.

Возможно ли создание в BEMHTML глобальной переменной доступной для всех шаблонов? т.е. например я хочу иметь объект к которому есть доступ из контекста любого шаблона.

Ввиду нетривиальных конфигов enb(Возможно только для меня), не понятно как использовать BH на клиенте. Хотелось бы посмотреть примеры использования. Интересно, какова судьба BEMHTML в связи с появлением BH.

Всем привет. Как заставить BEMHTML генерить не сжатый, а нормальный "бьютифицированный" код HTML? Спасибо.

Не могу разобраться с шаблонизацией на клиенте. Есть два блока content и list. Как сделать чтобы из блока content был виден шаблон list? Какие зависимости надо подключать и в каком порядке?

пробовал так:

modules.define('i-bem__dom', ['BEMHTML'], function(provide, BEMHTML, BEMDOM) {
    BEMDOM.decl('content', {
        onSetMod: {
            'js':{
                'inited': function(){
                    BEMDOM.append(
                        this.domElem,
                        BEMHTML.apply(
                            {
                                block: 'list'
                            })
                        );
                }
            }
        }
    });
provide(BEMDOM);

});

Дима Белицкий, в своем докладе в Москве выносит все миксы блоков в bemhtml блока, хотелось бы узнать насколько это правильно, выходит надо выносить миксы и модификаторы? Вообщем вопрос в том, когда стоит выносить сущности, а когда нет в bemhtml.

Да, и отсортируте плз теги по алфавиту

Правильно ли будет вынести content (текст) блока в bemhtml шаблон.

Блок используется в нескольких местах с одинаковым содержимым (текстом), ведь прописывать один и тот же текст в разных местах плохое решение

Есть БЭМ блок, у которого прописаны свои поведения. Изначально его на странице нет. но в deps он прописан поэтому все исходники подгружаются. Так вот. Надо чтобы по событию нажатия кнопки, в DOM добавлялся этот блок. Таких блоков может быть добавлено много. Необходимо чтобы он при всем при том еще и работал. Каким образом это сделать?

Есть какое-то стандартное решение?

Подскажите как создать блок BEM (в идеале из BEMJSON) в runtime, например по событию нажатия на кнопку, и добавить его в к содержимому другого блока.

Решил я попробовать обернуть сторонний виджет в блок БЭМ, возьмем например Yandex Share

<script type="text/javascript" src="//yandex.st/share/share.js" 
    charset="utf-8"></script>
<div class="yashare-auto-init" data-yashareL10n="ru" 
    data-yashareQuickServices="vkontakte,facebook" data-yashareTheme="counter"></div>

Я создаю блок bem create -l desktop.blocks -b yashare с содержимым

# desktop.blocks/yashare/yashare.bemhtml
`block('yashare')(
    tag()('div'),
    bem()(false),
    cls()('yashare-auto-init'),
    attrs()({'data-yashareQuickServices': '...', 'data-yashareTheme': '...')
)
/* desktop.blocks/yashare/yashare.browser.js */
modules.define('yashare', ['loader_type_js'], function(provide, loader) {
    loader('//yandex.st/share/share.js', provide);
});

А теперь вопрос, как воспользоваться данным блоком, чтоб подключения share.js было единожды (это уже реализует loader), но только в случае наличия на странице блоков yashare?

Если в yashare.browser.js добавить modules.require(['yashare'], function() {}); то подключение скрипта будет вне зависимости от наличия на странице блоков.

В качестве виджета может быть и другой, главная задумка, что скрипт подключается единожды независимо от количества блоков (виджетов) на одной странице.

P.S. Из-за плохой, не структурированной, а местами просто устаревшей документации - очень высокий порог вхождения...

Кажется, я упустила что-то из документации по bemhtml. Хочу ответы на следующие простые вопросы:
1) как в bemhtml связать input-radio с label, когда radio не находится внутри label?
2) как определить в bemhtml input-radio и label, когда radio внутри label?
в обоих случаях radio одиночный.
Примеры видела, пост про radio (http://ru.bem.info/libs/bem-components/v2/desktop/radio/docs/) читала.

block('content')
(
    tag()('article'),

    elemMatch()
    (
        tag()(this.ctx.elem)
    )
);

Никак не пойму, почему не отрабатывает этот шаблон, а конкретно не подхватывает tag()('article'), если убрать из шаблона elemMatch() то тэг проставляется

Если есть у кого, прошу ссылочку. Хочется видеть сборку простого проекта с bemtree

Столкнулся с этой ошибкой когда решил положить блоки и бандлы в папку src/ на проекте и настроить сборку так.

/
    .bem/
    src/
       desktop.blocks
       desktop.bundles

в make.js соответственно указал

getBundlesLevels: function() {
        return [
            'src/desktop.bundles'
        ];
    }

Сборка происходит нормально, но в такой схеме сервер падает на этом then

BEMTREE.apply(json)
        .then(function(bemjson) {
            res.send(BEMHTML.apply(bemjson));
        });

А если положить эти же папки, блоков и бандлов, в корень то все отрабатывает как надо.

Подскажике как поправить и настроить предложенную выше схему.

Весь кусок про сервер и шаблонизацию

    var bemtreeTemplate = FS.readFileSync( './src/desktop.bundles/index/_index.bemtree.js'),
        bemtmlTemplate = FS.readFileSync( './src/desktop.bundles/index/_index.bemhtml.js');


    var context = VM.createContext({
        Vow: vow,
        console: console,
        borschik: {
            link: function(i) {
                return i;
            }
        }
    });

    VM.runInContext(bemtreeTemplate, context);
    BEMTREE = context.BEMTREE;

    VM.runInContext(bemtmlTemplate, context);
    BEMHTML = context.BEMHTML;

    BEMTREE.apply(json)
        .then(function(bemjson) {
            res.send(BEMHTML.apply(bemjson));
        });

До сих пор не могу понять магию apply, applyNext, applyCtx хотя ни раз читал ман по ним

Вообще мне нужно изменить элемент на ссылку, если в параметрах есть url, я сделал так

block('nav').elem('item')
(
    match(this.ctx.url)
    (
        function()
        {
            this.ctx.block = 'link';

            delete this.ctx.elem;

            this.ctx.mix   = [
                {
                    block: this.block,
                    elem: 'item'
                }
            ];

            applyCtx(this.ctx);
        }
    )
);

Получаю бесконечную рекурсию - [RangeError: Maximum call stack size exceeded]

Сейчас я поставил такой костыль:

block('nav').elem('item')
(
    match(this.ctx.url && !this.ctx._prepared)
    (
        function()
        {
            this.ctx.block     = 'link';
            this.ctx._prepared = true;

            delete this.ctx.elem;

            this.ctx.mix   = [
                {
                    block: this.block,
                    elem: 'item'
                }
            ];

            applyCtx(this.ctx);
        }
    )
);

Как сделать правильно?

Входящие: Есть редктор, который сохраняет примерно такие данные

post.html = '<p>\r\n\t\tСтремление к совершенству – пожалуй, именно так можно описать развитие человечества. Вот взять, к примеру, женскую красоту. Чего только не сделают девушки, чтобы оказаться самой красивой. ... .</p>\r\n\t<!-- gallery(3) --><p>\r\n\tА вот раньше оверклокинг существовал исключительно ради выгоды. ... </p><p><!-- gallery(4) --></p>'

В этой строке есть вставки коментариев. Задача: В контексте bemtree хочу заменить комнтарии на html код блока галлереи с слайдером. Хоче сделать примерно следующее:

post.galleries.map(function(gallery, index) {
        var id = post.galleries_list[index].id,
            images = post.galleries[index].images,

            galleryBlock = {
                block : 'slider',
                slides : images
            }; //Здесь что-то нужно сделать что бы распарсить блок в строку

        post.html = post.html.replace('<!-- gallery(' + id +') -->', galleryBlock)
    })

Вопрос: Как в bemtree/bemhtml распарсить блок в html строку? Или предложите другие варианты решения проблемы?