UNPKG

postcss-pseudo-content-insert

Version:

PostCSS plugin inserts an empty content block into your :before and :after pseudo elements if it is missing

97 lines (81 loc) 3.26 kB
var postcss = require('postcss'); module.exports = postcss.plugin('postcss-pseudo-content-insert', function (opts) { opts = opts || {}; // Removes an element from an array. // String value: the value to search and remove. // return: an array with the removed element; false otherwise. function removeFromArray(arr, selector) { var idx = arr.indexOf(selector); if (idx !== -1) { return arr.splice(idx, 1); } return false; } // Checks to see if a value exists in an array function arrayHasValue(arr, value) { var idx = arr.indexOf(value); if (idx !== -1) { return true; } return false; } // Adds an element to an array // Checks to see if it exists function addToArray(arr, selector) { if(!arrayHasValue(arr, selector)) arr.push(selector); } // Define array for seelectors with missing content & present var contentAwaiting = []; var contentPresent = []; return function (css) { var customPseudoExp = /(.*::?)(after|before)$/; // Step over each rule css.walkRules(function (rule) { // If there is more than one selector, loop over each // and if there is content missing, add to array if(rule.selectors.length > 1) { rule.selectors.forEach(function (selector) { var hasContent = false; if(customPseudoExp.test(selector)) { rule.walkDecls(function transformDecl(decl) { // If the property = content, assign flag to true if(decl.prop === 'content') hasContent = true; }); if(!hasContent) addToArray(contentAwaiting, selector); else addToArray(contentPresent, selector); } }); } }); // Step again css.walkRules(function (rule) { // Loop again, this time only rules that have 1 selector // only. If content is missing, add it. // Then remove the selector from the contentAwaiting array if(rule.selectors.length === 1) { var hasContent = false; if(customPseudoExp.test(rule.selector)) { rule.walkDecls(function transformDecl(decl) { // If the property = content, assign flag to true if(decl.prop === 'content') hasContent = true; }); if(!hasContent) rule.append({ prop: 'content', value: '\'\'' }); // Remove the selector from contentAwaiting array removeFromArray(contentAwaiting, rule.selector); } } }); for (var i = 0; i < contentAwaiting.length; i++) { css.append(postcss.rule({ selector: contentAwaiting[i] }).append({ prop: 'content', value: '\'\'' })); } }; });