UNPKG

@sequencemedia/css-purge

Version:

A CSS tool written in Node JS as a command line app or library for the purging, burning, reducing, shortening, compressing, cleaning, trimming and formatting of duplicate, extra, excess or bloated CSS.

163 lines (138 loc) 5.62 kB
import debug from 'debug' import hasPropertyBorder from '#utils/declarations/has-property-border' import hasPropertyBorderWidth from '#utils/declarations/has-property-border-width' import hasPropertyBorderStyle from '#utils/declarations/has-property-border-style' import hasPropertyBorderColor from '#utils/declarations/has-property-border-color' import hasInherit from '#utils/has-inherit' import hasImportant from '#utils/has-important' import toProperty from '#utils/to-property' import toValue from '#utils/to-value' import getValueOfTriProp from '#utils/get-value-of-tri-prop' /** * Preserve order */ const DEFAULT_BORDER_PROPERTIES = [ 'border-width', 'border-style', 'border-color' ] // https://www.w3.org/TR/CSS21/box.html#border-shorthand-properties const DEFAULT_BORDER_VALUES = [ '0', '', '' ] function hasBorder (properties) { return properties.includes('border') || ( properties.includes('border-width') && properties.includes('border-style') && properties.includes('border-color') ) } const log = debug('@sequencemedia/css-purge/process-border') export default function processBorder (rule, OPTIONS, SUMMARY) { const { declarations = [] } = rule if (declarations.length) { const border = declarations.filter(hasPropertyBorder) if (!border.some(hasInherit)) { let borderProperties = border.map(toProperty) if (hasBorder(borderProperties)) { const { selectors = [] } = rule log(selectors) // .join(', ').trim()) let borderValues = border.map(toValue) const borderWidthIndex = borderProperties.indexOf('border-width') const borderStyleIndex = borderProperties.indexOf('border-style') const borderColorIndex = borderProperties.indexOf('border-color') const borderWidthValue = borderValues[borderWidthIndex] ?? '' const borderStyleValue = borderValues[borderStyleIndex] ?? '' const borderColorValue = borderValues[borderColorIndex] ?? '' if ( borderWidthValue.split(' ').length === 1 && // multi-width values not allowed borderColorValue.split(' ').length === 1 // multi-color (border around squares, etc.) check - only do if single ) { let BORDER_VALUES = [ borderWidthValue, borderStyleValue, borderColorValue ] // existing border check if (borderProperties.includes('border')) { const borderPropValueIndex = borderProperties.indexOf('border') const borderPropValue = borderValues[borderPropValueIndex] if (borderPropValue !== 'none') { if (borderWidthIndex > borderPropValueIndex) { BORDER_VALUES[0] = borderWidthValue } else { const propValue = getValueOfTriProp(borderPropValue, 'width') if (propValue) BORDER_VALUES[0] = propValue } if (borderProperties.indexOf('border-style') > borderPropValueIndex) { BORDER_VALUES[1] = borderStyleValue } else { const propValue = getValueOfTriProp(borderPropValue, 'style') if (propValue) BORDER_VALUES[1] = propValue } if (borderColorIndex > borderPropValueIndex) { BORDER_VALUES[2] = borderColorValue } else { const propValue = getValueOfTriProp(borderPropValue, 'color') if (propValue) BORDER_VALUES[2] = propValue } } else { BORDER_VALUES = [ ...DEFAULT_BORDER_VALUES ] } } if (!BORDER_VALUES.every((v) => v === '')) { borderProperties = [ ...DEFAULT_BORDER_PROPERTIES ] borderValues = BORDER_VALUES } // check for !important if (borderValues.some(hasImportant)) { borderValues = borderValues.map((border) => border.replace(/(!important)/g, '')) borderValues[borderValues.length - 1] += ' !important' } // add declaration if (declarations.some(hasPropertyBorder)) { const i = declarations.findIndex(hasPropertyBorder) declarations.splice(i, 0, { type: 'declaration', property: 'border', value: borderValues.filter(Boolean).join(' ') // remove empty values }) SUMMARY.stats.summary.noBordersShortened += 1 } if (declarations.some(hasPropertyBorderWidth)) { const i = declarations.findIndex(hasPropertyBorderWidth) declarations.splice(i, 1) } if (declarations.some(hasPropertyBorderStyle)) { const i = declarations.findIndex(hasPropertyBorderStyle) declarations.splice(i, 1) } if (declarations.some(hasPropertyBorderColor)) { const i = declarations.findIndex(hasPropertyBorderColor) declarations.splice(i, 1) } // remove existing borders const properties = declarations.filter(toProperty).map(toProperty) const j = properties.filter((property) => property === 'border').length if (j > 1) { for (let i = 1; i < j; ++i) { const was = properties.indexOf('border') const now = properties.indexOf('border', (was + 1)) declarations.splice(now, 1) } } } // end of inherit check } } } }