UNPKG

gulp-webp-css-splitter

Version:

Duplicate background images with webp. Add .webp and .no-webp classes. Minify result css

115 lines (104 loc) 5.36 kB
const pluginName = 'gulp-webp-css-splitter'; const PluginError = require('gulp-util/lib/PluginError'); const through = require('through2'); var CSSParser = require('css'); var supportsRender = function (rulesArr) { return rulesArr.join(""); } module.exports = function(extensions){ var extensions = extensions || ['.jpg','.png']; return through.obj(function(file, enc, cb) { if (file.isNull()) { cb(null, file); return; } if (file.isStream()) { cb(new PluginError(pluginName, 'Streaming not supported')); return; } try { var css = file.contents.toString(); var obj = CSSParser.parse(css); if (!obj) return; var getWebpRulesArr = function (arr) { var webpLine = function(selectors, rule){ var line = selectors + ' {\n' + rule + '}\n'; return line; } var retn = { webpArrStr: [], originalArrStr: [], media: {}, mediaOrig: {} } Object.keys(arr).forEach(function (k) { var rule = arr[k]; // Если CSS правило if(rule.type == 'rule'){ var declarations = rule.declarations; // Перебираем декларации var regularRules = ''; var currentSelector = ''; Object.keys(declarations).forEach(function (i) { var declaration = declarations[i]; // Если находим background: url без .webp или .svg if ((declaration.property.indexOf('background') + 1) && (declaration.value.indexOf('url') + 1) && !(declaration.value.indexOf('.webp') + 1) && !(declaration.value.indexOf('.svg') + 1)){ var newValue = declaration.value; // Заменяем на webp for(ext in extensions){ newValue = newValue.replace(extensions[ext],'.webp'); } // Формируем строку и пушим в массив дополнений currentSelector = rule.selectors.join(','); var newRule = '\t' + declaration.property + ':' + newValue; var pushStr = webpLine('.webp ' + currentSelector,newRule); retn.webpArrStr.push(pushStr); var oldRule = '\t' + declaration.property + ':' + declaration.value; var pushStr = webpLine('.no-webp ' + currentSelector,oldRule); retn.webpArrStr.push(pushStr); } else { currentSelector = rule.selectors.join(','); regularRules = regularRules + '\t' +declaration.property + ':' + declaration.value + ';\n'; } }); if(regularRules != '') { var pushStr = webpLine(currentSelector, regularRules); retn.originalArrStr.push(pushStr); } // Если медиа-запрос }else if(rule.type == 'media'){ var retnStr = getWebpRulesArr(rule.rules); if (!!retn.media[rule.media]){ retn.media[rule.media] = retn.media[rule.media].concat(retnStr.webpArrStr); }else{ retn.media[rule.media] = retnStr.webpArrStr; } if (!!retn.mediaOrig[rule.media]){ retn.mediaOrig[rule.media] = retn.mediaOrig[rule.media].concat(retnStr.originalArrStr); }else{ retn.mediaOrig[rule.media] = retnStr.originalArrStr; } } }); return retn; } // Получаем доп правила var newrules = getWebpRulesArr(obj.stylesheet.rules); // Собираем строку с webp var newRulesStr = supportsRender(newrules.webpArrStr); // Собираем строку с оригинальными картинками var oldRulesStr = supportsRender(newrules.originalArrStr); // Добавляем медиа-правила for(k in newrules.media){ newRulesStr += "\n @media " + k + "{\n" + supportsRender(newrules.media[k]) + "}\n"; } const data = oldRulesStr.concat(newRulesStr); file.contents = new Buffer(data); this.push(file); } catch (err) { this.emit('error', new PluginError(pluginName, err)); } cb(); }); };