| [9af201e] | 1 | 'use strict';
|
|---|
| 2 | const stylehacks = require('stylehacks');
|
|---|
| 3 | const canMerge = require('../canMerge.js');
|
|---|
| 4 | const getDecls = require('../getDecls.js');
|
|---|
| 5 | const minifyTrbl = require('../minifyTrbl.js');
|
|---|
| 6 | const parseTrbl = require('../parseTrbl.js');
|
|---|
| 7 | const insertCloned = require('../insertCloned.js');
|
|---|
| 8 | const mergeRules = require('../mergeRules.js');
|
|---|
| 9 | const mergeValues = require('../mergeValues.js');
|
|---|
| 10 | const trbl = require('../trbl.js');
|
|---|
| 11 | const isCustomProp = require('../isCustomProp.js');
|
|---|
| 12 | const canExplode = require('../canExplode.js');
|
|---|
| 13 |
|
|---|
| 14 | /**
|
|---|
| 15 | * @param {string} prop
|
|---|
| 16 | * @return {{explode: (rule: import('postcss').Rule) => void, merge: (rule: import('postcss').Rule) => void}}
|
|---|
| 17 | */
|
|---|
| 18 | module.exports = (prop) => {
|
|---|
| 19 | const properties = trbl.map((direction) => `${prop}-${direction}`);
|
|---|
| 20 | /** @type {(rule: import('postcss').Rule) => void} */
|
|---|
| 21 | const cleanup = (rule) => {
|
|---|
| 22 | let decls = getDecls(rule, [prop].concat(properties));
|
|---|
| 23 |
|
|---|
| 24 | while (decls.length) {
|
|---|
| 25 | const lastNode = decls[decls.length - 1];
|
|---|
| 26 |
|
|---|
| 27 | // remove properties of lower precedence
|
|---|
| 28 | const lesser = decls.filter(
|
|---|
| 29 | (node) =>
|
|---|
| 30 | !stylehacks.detect(lastNode) &&
|
|---|
| 31 | !stylehacks.detect(node) &&
|
|---|
| 32 | node !== lastNode &&
|
|---|
| 33 | node.important === lastNode.important &&
|
|---|
| 34 | lastNode.prop === prop &&
|
|---|
| 35 | node.prop !== lastNode.prop
|
|---|
| 36 | );
|
|---|
| 37 |
|
|---|
| 38 | for (const node of lesser) {
|
|---|
| 39 | node.remove();
|
|---|
| 40 | }
|
|---|
| 41 | decls = decls.filter((node) => !lesser.includes(node));
|
|---|
| 42 |
|
|---|
| 43 | // get duplicate properties
|
|---|
| 44 | let duplicates = decls.filter(
|
|---|
| 45 | (node) =>
|
|---|
| 46 | !stylehacks.detect(lastNode) &&
|
|---|
| 47 | !stylehacks.detect(node) &&
|
|---|
| 48 | node !== lastNode &&
|
|---|
| 49 | node.important === lastNode.important &&
|
|---|
| 50 | node.prop === lastNode.prop &&
|
|---|
| 51 | !(!isCustomProp(node) && isCustomProp(lastNode))
|
|---|
| 52 | );
|
|---|
| 53 |
|
|---|
| 54 | for (const node of duplicates) {
|
|---|
| 55 | node.remove();
|
|---|
| 56 | }
|
|---|
| 57 | decls = decls.filter(
|
|---|
| 58 | (node) => node !== lastNode && !duplicates.includes(node)
|
|---|
| 59 | );
|
|---|
| 60 | }
|
|---|
| 61 | };
|
|---|
| 62 |
|
|---|
| 63 | const processor = {
|
|---|
| 64 | /** @type {(rule: import('postcss').Rule) => void} */
|
|---|
| 65 | explode: (rule) => {
|
|---|
| 66 | rule.walkDecls(new RegExp('^' + prop + '$', 'i'), (decl) => {
|
|---|
| 67 | if (!canExplode(decl)) {
|
|---|
| 68 | return;
|
|---|
| 69 | }
|
|---|
| 70 |
|
|---|
| 71 | if (stylehacks.detect(decl)) {
|
|---|
| 72 | return;
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | const values = parseTrbl(decl.value);
|
|---|
| 76 |
|
|---|
| 77 | trbl.forEach((direction, index) => {
|
|---|
| 78 | insertCloned(
|
|---|
| 79 | /** @type {import('postcss').Rule} */ (decl.parent),
|
|---|
| 80 | decl,
|
|---|
| 81 | {
|
|---|
| 82 | prop: properties[index],
|
|---|
| 83 | value: values[index],
|
|---|
| 84 | }
|
|---|
| 85 | );
|
|---|
| 86 | });
|
|---|
| 87 |
|
|---|
| 88 | decl.remove();
|
|---|
| 89 | });
|
|---|
| 90 | },
|
|---|
| 91 | /** @type {(rule: import('postcss').Rule) => void} */
|
|---|
| 92 | merge: (rule) => {
|
|---|
| 93 | mergeRules(rule, properties, (rules, lastNode) => {
|
|---|
| 94 | if (canMerge(rules) && !rules.some(stylehacks.detect)) {
|
|---|
| 95 | insertCloned(
|
|---|
| 96 | /** @type {import('postcss').Rule} */ (lastNode.parent),
|
|---|
| 97 | lastNode,
|
|---|
| 98 | {
|
|---|
| 99 | prop,
|
|---|
| 100 | value: minifyTrbl(mergeValues(...rules)),
|
|---|
| 101 | }
|
|---|
| 102 | );
|
|---|
| 103 | for (const node of rules) {
|
|---|
| 104 | node.remove();
|
|---|
| 105 | }
|
|---|
| 106 |
|
|---|
| 107 | return true;
|
|---|
| 108 | }
|
|---|
| 109 | return false;
|
|---|
| 110 | });
|
|---|
| 111 |
|
|---|
| 112 | cleanup(rule);
|
|---|
| 113 | },
|
|---|
| 114 | };
|
|---|
| 115 |
|
|---|
| 116 | return processor;
|
|---|
| 117 | };
|
|---|