Skip to content

Instantly share code, notes, and snippets.

@ryelle
Created April 22, 2020 23:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryelle/17068a397d3314c86daadec2de17531e to your computer and use it in GitHub Desktop.
Save ryelle/17068a397d3314c86daadec2de17531e to your computer and use it in GitHub Desktop.
PostCSS plugin to remove colors from a CSS file
const postcss = require( 'postcss' );
const getColors = require( 'get-css-colors' );
/* A size is any number, optionally with a unit. */
const isSize = ( value ) => /^\d+\s?([a-zA-Z]+)?$/.test( value.trim() );
/* If the value has a color in it, getColors will return an array. */
const isColor = ( value ) => null !== getColors( value );
/* A line style is from a set of values */
const isLineStyle = ( value ) =>
-1 !==
[
'auto', // Technically only allowed on outline.
'none',
'hidden',
'dotted',
'dashed',
'solid',
'double',
'groove',
'ridge',
'inset',
'outset',
].indexOf( value );
function explodeProp( decl ) {
switch ( decl.prop ) {
case 'border':
case 'border-top':
case 'border-right':
case 'border-bottom':
case 'border-left':
case 'outline':
const values = decl.value.split( ' ' );
values.forEach( ( value ) => {
if ( isLineStyle( value ) ) {
decl.before(
postcss.decl( { prop: decl.prop + '-style', value } )
);
} else if (
isSize( value ) ||
-1 !== [ 'thin', 'medium', 'thick' ].indexOf( value )
) {
decl.before(
postcss.decl( { prop: decl.prop + '-width', value } )
);
} else if ( isColor( value ) ) {
decl.before(
postcss.decl( { prop: decl.prop + '-color', value } )
);
}
} );
decl.remove();
break;
}
}
module.exports = postcss.plugin( 'remove-colors', function() {
return function( root ) {
root.walkRules( ( rule ) => {
// Explode out the border/outline props.
rule.walkDecls( ( decl ) => {
explodeProp( decl );
} );
// Remove any declarations that have color.
rule.walkDecls( ( decl ) => {
const hasColors = getColors( decl.value );
// grayscale isn't actually a color, it's used in antialiasing.
if ( 'grayscale' === decl.value ) {
return;
}
if ( Array.isArray( hasColors ) ) {
let value = decl.value.slice();
hasColors.forEach( ( color ) => {
value = value.replace( color, '' );
} );
decl.remove();
}
} );
} );
// Remove all empty rule blocks.
root.walkRules( ( rule ) => {
if ( rule.nodes && 0 === rule.nodes.length ) {
rule.remove();
}
} );
// Remove all empty @rule blocks.
root.walkAtRules( ( rule ) => {
if ( rule.nodes && 0 === rule.nodes.length ) {
rule.remove();
}
} );
};
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment