63 lines
1.7 KiB
JavaScript
63 lines
1.7 KiB
JavaScript
const isPlainObject = require('lodash.isplainobject')
|
|
|
|
const parser = require('postcss-selector-parser')
|
|
const parseSelector = parser()
|
|
|
|
module.exports = {
|
|
isUsableColor(color, values) {
|
|
return isPlainObject(values) && color !== 'gray' && values[600]
|
|
},
|
|
|
|
/**
|
|
* @param {string} selector
|
|
*/
|
|
commonTrailingPseudos(selector) {
|
|
let ast = parseSelector.astSync(selector)
|
|
|
|
/** @type {import('postcss-selector-parser').Pseudo[][]} */
|
|
let matrix = []
|
|
|
|
// Put the pseudo elements in reverse order in a sparse, column-major 2D array
|
|
for (let [i, sel] of ast.nodes.entries()) {
|
|
for (const [j, child] of [...sel.nodes].reverse().entries()) {
|
|
// We only care about pseudo elements
|
|
if (child.type !== 'pseudo' || !child.value.startsWith('::')) {
|
|
break
|
|
}
|
|
|
|
matrix[j] = matrix[j] || []
|
|
matrix[j][i] = child
|
|
}
|
|
}
|
|
|
|
let trailingPseudos = parser.selector()
|
|
|
|
// At this point the pseudo elements are in a column-major 2D array
|
|
// This means each row contains one "column" of pseudo elements from each selector
|
|
// We can compare all the pseudo elements in a row to see if they are the same
|
|
for (const pseudos of matrix) {
|
|
// It's a sparse 2D array so there are going to be holes in the rows
|
|
// We skip those
|
|
if (!pseudos) {
|
|
continue
|
|
}
|
|
|
|
let values = new Set([...pseudos.map((p) => p.value)])
|
|
|
|
// The pseudo elements are not the same
|
|
if (values.size > 1) {
|
|
break
|
|
}
|
|
|
|
pseudos.forEach((pseudo) => pseudo.remove())
|
|
trailingPseudos.prepend(pseudos[0])
|
|
}
|
|
|
|
if (trailingPseudos.nodes.length) {
|
|
return [trailingPseudos.toString(), ast.toString()]
|
|
}
|
|
|
|
return [null, selector]
|
|
},
|
|
}
|