tadatuta / enb-css-hash

ENB tech to build a hash with entities as a key and CSS inlined as a value
Other
2 stars 1 forks source link

Why? :) #1

Open vitkarpov opened 7 years ago

vitkarpov commented 7 years ago

Why do you need this tech? Where it could be used?

tadatuta commented 7 years ago

I'll provide some docs in a while but it should be used with template to inline styles before first occurrence of each entity:

oninit(function(exports) {
    var ptp = exports.BEMContext.prototype;

    ptp._pushedCSS = {};

    ptp._entitiesCSS = require('../css.json');

    ptp._onNode = function(node) {
        if (!node) return [];
        if (typeof node === 'string') return [node];

        node.mods || (node.mods = {});
        node.elemMods || (node.elemMods = {});

        var entities = [node.elem ? node.block + '__' + node.elem : node.block],
            modNames = Object.keys(node.mods),
            elemModNames = Object.keys(node.elemMods);

        modNames.concat(elemModNames).forEach(function(modName) {
            var buf = node.block;
            node.elem && (buf += '__' + node.elem);
            buf += '_' + modName;

            var modVal = node.elemMods[modName] || node.mods[modName];

            if (modVal && modVal !== true) {
                buf += '_' + modVal;
            }

            entities.push(buf);
        }, this);

        return entities;
    };
});

// TODO: replace()
block('*').match(function() { return this.block; }).def()(function() {
    var _this = this,
        entities = [].concat(this.ctx.mix || [], apply('mix') || []).reduce(function(acc, item) {
            return acc.concat(_this._onNode(item));
        }, this._onNode(this)),
        reqid = BEM._reqid;

    // `this._pushedCSS[reqid]` should be deleted after each request
    this._pushedCSS[reqid] || (this._pushedCSS[reqid] = {});

    var reqCss = this._pushedCSS[reqid],
        styles = [];

    entities.forEach(function(entityKey) {
        var entityCss = this._entitiesCSS[entityKey];

        if (!entityCss || (reqCss && reqCss[entityKey])) return;

        reqCss[entityKey] = true;

        // custom logic for `page` not to break `doctype`, etc.
        if (entityKey === 'page' && this.ctx.head) {
            this.ctx.head.push({
                elem: 'css',
                content: entityCss
            });

            return;
        }

        styles.push(entityCss);
    }, this);

    return styles.length ? [
        '<style>',
        styles.join(''),
        '</style>',
        applyNext()
    ].join('') : applyNext();
});