mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-04 18:49:30 +08:00
117 lines
3.2 KiB
Text
117 lines
3.2 KiB
Text
'use strict';
|
|
const stylehacks = require('stylehacks');
|
|
const canMerge = require('../canMerge.js');
|
|
const getDecls = require('../getDecls.js');
|
|
const minifyTrbl = require('../minifyTrbl.js');
|
|
const parseTrbl = require('../parseTrbl.js');
|
|
const insertCloned = require('../insertCloned.js');
|
|
const mergeRules = require('../mergeRules.js');
|
|
const mergeValues = require('../mergeValues.js');
|
|
const trbl = require('../trbl.js');
|
|
const isCustomProp = require('../isCustomProp.js');
|
|
const canExplode = require('../canExplode.js');
|
|
|
|
/**
|
|
* @param {string} prop
|
|
* @return {{explode: (rule: import('postcss').Rule) => void, merge: (rule: import('postcss').Rule) => void}}
|
|
*/
|
|
module.exports = (prop) => {
|
|
const properties = trbl.map((direction) => `${prop}-${direction}`);
|
|
/** @type {(rule: import('postcss').Rule) => void} */
|
|
const cleanup = (rule) => {
|
|
let decls = getDecls(rule, [prop].concat(properties));
|
|
|
|
while (decls.length) {
|
|
const lastNode = decls[decls.length - 1];
|
|
|
|
// remove properties of lower precedence
|
|
const lesser = decls.filter(
|
|
(node) =>
|
|
!stylehacks.detect(lastNode) &&
|
|
!stylehacks.detect(node) &&
|
|
node !== lastNode &&
|
|
node.important === lastNode.important &&
|
|
lastNode.prop === prop &&
|
|
node.prop !== lastNode.prop
|
|
);
|
|
|
|
for (const node of lesser) {
|
|
node.remove();
|
|
}
|
|
decls = decls.filter((node) => !lesser.includes(node));
|
|
|
|
// get duplicate properties
|
|
let duplicates = decls.filter(
|
|
(node) =>
|
|
!stylehacks.detect(lastNode) &&
|
|
!stylehacks.detect(node) &&
|
|
node !== lastNode &&
|
|
node.important === lastNode.important &&
|
|
node.prop === lastNode.prop &&
|
|
!(!isCustomProp(node) && isCustomProp(lastNode))
|
|
);
|
|
|
|
for (const node of duplicates) {
|
|
node.remove();
|
|
}
|
|
decls = decls.filter(
|
|
(node) => node !== lastNode && !duplicates.includes(node)
|
|
);
|
|
}
|
|
};
|
|
|
|
const processor = {
|
|
/** @type {(rule: import('postcss').Rule) => void} */
|
|
explode: (rule) => {
|
|
rule.walkDecls(new RegExp('^' + prop + '$', 'i'), (decl) => {
|
|
if (!canExplode(decl)) {
|
|
return;
|
|
}
|
|
|
|
if (stylehacks.detect(decl)) {
|
|
return;
|
|
}
|
|
|
|
const values = parseTrbl(decl.value);
|
|
|
|
trbl.forEach((direction, index) => {
|
|
insertCloned(
|
|
/** @type {import('postcss').Rule} */ (decl.parent),
|
|
decl,
|
|
{
|
|
prop: properties[index],
|
|
value: values[index],
|
|
}
|
|
);
|
|
});
|
|
|
|
decl.remove();
|
|
});
|
|
},
|
|
/** @type {(rule: import('postcss').Rule) => void} */
|
|
merge: (rule) => {
|
|
mergeRules(rule, properties, (rules, lastNode) => {
|
|
if (canMerge(rules) && !rules.some(stylehacks.detect)) {
|
|
insertCloned(
|
|
/** @type {import('postcss').Rule} */ (lastNode.parent),
|
|
lastNode,
|
|
{
|
|
prop,
|
|
value: minifyTrbl(mergeValues(...rules)),
|
|
}
|
|
);
|
|
for (const node of rules) {
|
|
node.remove();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
cleanup(rule);
|
|
},
|
|
};
|
|
|
|
return processor;
|
|
};
|