all files / src/Actions/actions/ MergeDeclarations.js

90.99% Statements 101/111
77.36% Branches 41/53
88.89% Functions 8/9
90.65% Lines 97/107
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177            69× 69× 69× 69× 69× 69× 69× 69× 69× 69× 69× 69× 69×     69× 69× 69× 69× 69× 74× 69× 69×         69× 69× 69× 69× 69× 69× 69× 69× 69× 69× 151× 151× 151×     151×       151× 36×   157× 92× 104× 92× 92× 92× 83× 83× 83×                       23×     69× 69×     20× 20×         20×                   599× 599× 628× 139× 139×           489× 438× 438×           51× 25× 20×         26×             22×             598× 135× 459×         83×     600×    
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const template_api_1 = require("@opticss/template-api");
const postcss = require("postcss");
const selectorParser = require("postcss-selector-parser");
const postcss_selector_parser_1 = require("postcss-selector-parser");
const cssIntrospection_1 = require("../../util/cssIntrospection");
const Action_1 = require("../Action");
const { isAttribute, isClassName, isIdentifier, isPseudo, isPseudoElement, isTag, isUniversal, } = selectorParser;
const REWRITEABLE_ATTR_OPS = ["=", "~=", undefined];
/**
 * Merges duplicate declarations from multiple rule sets into a new rule set.
 */
class MergeDeclarations extends Action_1.MultiAction {
    constructor(templateOptions, pass, selectorContext, decl, declInfos, optimization, reason) {
        super(optimization);
        this.templateOptions = templateOptions;
        this.styleMapping = pass.styleMapping;
        this.reason = reason;
        this.container = declInfos[0].selectorInfo.container;
        this.selectorContext = selectorContext;
        this.cache = pass.cache;
        this.identGenerators = pass.identGenerators;
        this.decl = decl;
        this.declInfos = declInfos;
        this.removedRules = [];
        this.removedAtRules = [];
        this.removedSelectors = new Array();
    }
    perform() {
        let classname = this.identGenerators.nextIdent("class");
        let newSelector;
        Eif (this.selectorContext) {
            let key = this.selectorContext.key;
            let nodes = key.nodes;
            key.nodes = nodes.map(n => isUniversal(n) ? selectorParser.className({ value: classname }) : n);
            newSelector = this.selectorContext.toString();
            key.nodes = nodes;
        }
        else {
            newSelector = `.${classname}`;
        }
        this.newRule = postcss.rule({ selector: newSelector });
        this.newRule.raws = { before: "\n", after: " ", semicolon: true };
        let decl = postcss.decl(this.decl);
        decl.raws = { before: " ", after: " " };
        this.newRule.append(decl);
        let insertionDecl = this.declInfos[0];
        let ruleLocation = insertionDecl.selectorInfo.rule;
        this.container.insertBefore(ruleLocation, this.newRule);
        let sourceAttributes = new Array();
        for (let declInfo of this.declInfos) {
            let sel = declInfo.selectorInfo.selector.key;
            let inputs = MergeDeclarations.inputsFromSelector(this.templateOptions, sel);
            Iif (!inputs) {
                throw new Error("internal error");
            }
            sourceAttributes.push({
                existing: inputs,
                unless: new Array(),
            });
            if (declInfo.decl.parent === undefined) {
                continue; // TODO: take this out -- it shouldn't happen.
            }
            if (declInfo.decl.parent.nodes.filter(node => node.type === "decl").length === 1) {
                let rule = declInfo.decl.parent;
                let newlyRemoved = this.cache.getParsedSelectors(rule).map(s => ({ parsedSelector: s, rule }));
                this.removedSelectors.splice(0, 0, ...newlyRemoved);
                let ruleParent = rule.parent;
                if (ruleParent) {
                    this.removedRules.push(rule);
                    ruleParent.removeChild(rule);
                    if (!hasMeaningfulChildren(ruleParent)) {
                        Eif (cssIntrospection_1.isAtRule(ruleParent)) {
                            this.removedAtRules.push(ruleParent);
                            ruleParent.remove();
                        }
                        else if (postcss_selector_parser_1.isRoot(ruleParent)) {
                            // Empty stylesheet
                        }
                        else {
                            console.warn("this is a weird parent for a rule: ", ruleParent);
                        }
                    }
                }
            }
            else {
                declInfo.decl.remove();
            }
        }
        this.styleMapping.linkAttributes({ name: "class", value: classname }, sourceAttributes);
        return this;
    }
    logStrings() {
        let logs = new Array();
        this.declInfos.forEach((orig, i) => {
            let msg = `Declaration moved from "${orig.selectorInfo.selector}" into generated rule (${this.declString()}). ${this.reason} ${i + 1} of ${this.declInfos.length}.`;
            logs.push(this.annotateLogMessage(msg, this.nodeSourcePosition(orig.decl)));
        });
        this.removedRules.forEach(rule => {
            let msg = `Removed empty rule with selector "${rule.selector}".`;
            logs.push(this.annotateLogMessage(msg, this.nodeSourcePosition(rule)));
        });
        return logs;
    }
    declString(selector = this.newRule.selector) {
        return `${selector} { ${this.decl.prop}: ${this.decl.value}${this.decl.important ? " !important" : ""}; }`;
    }
    get sourcePosition() {
        return this.nodeSourcePosition(this.declInfos[0].decl);
    }
    /**
     * Returns the concrete html traits that the selector would match
     * or undefined if html traits aren't deducible from the selector.
     */
    static inputsFromSelector(templateOptions, sel) {
        let inputs = new Array();
        for (let node of sel.nodes) {
            if (isTag(node)) {
                Eif (templateOptions.analyzedTagnames) {
                    inputs.push({ tagname: node.value });
                }
                else {
                    return undefined;
                }
            }
            else if (isClassName(node)) {
                Eif (templateOptions.analyzedAttributes.includes("class")) {
                    inputs.push({ name: "class", value: node.value });
                }
                else {
                    return undefined;
                }
            }
            else if (isIdentifier(node)) {
                if (templateOptions.analyzedAttributes.includes("id")) {
                    inputs.push({ name: "id", value: node.value });
                }
                else {
                    return undefined;
                }
            }
            else if (isAttribute(node)) {
                Eif (REWRITEABLE_ATTR_OPS.includes(node.operator)
                    && isAttributeAnalyzed(templateOptions, node)) {
                    inputs.push({ name: node.attribute, value: node.value || "" });
                }
                else {
                    return undefined;
                }
            }
            else Eif (isPseudo(node) || isPseudoElement(node)) {
                // pass
            }
            else {
                return undefined;
            }
        }
        if (inputs.every(input => template_api_1.isSimpleTagname(input)))
            return undefined;
        return inputs;
    }
}
exports.MergeDeclarations = MergeDeclarations;
function isAttributeAnalyzed(templateOptions, node) {
    Iif (node.ns)
        return false;
    return templateOptions.analyzedAttributes.includes(node.attribute);
}
function hasMeaningfulChildren(container) {
    return container && container.nodes &&
        container.nodes.reduce(countNonCommentNodes, 0) > 0;
}
function countNonCommentNodes(count, n) {
    return n.type === "comment" ? count : count + 1;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVyZ2VEZWNsYXJhdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvQWN0aW9ucy9hY3Rpb25zL01lcmdlRGVjbGFyYXRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0Esd0RBTytCO0FBQy9CLG1DQUFtQztBQUNuQywwREFBMEQ7QUFDMUQscUVBQWlEO0FBZWpELGtFQUF1RDtBQUV2RCxzQ0FBd0M7QUFFeEMsTUFBTSxFQUNKLFdBQVcsRUFDWCxXQUFXLEVBQ1gsWUFBWSxFQUNaLFFBQVEsRUFDUixlQUFlLEVBQ2YsS0FBSyxFQUNMLFdBQVcsR0FDWixHQUFHLGNBQWMsQ0FBQztBQUVuQixNQUFNLG9CQUFvQixHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztBQVFwRDs7R0FFRztBQUNILHVCQUErQixTQUFRLG9CQUFXO0lBZWhELFlBQ0UsZUFBMkMsRUFDM0MsSUFBc0IsRUFDdEIsZUFBMkMsRUFDM0MsSUFBaUIsRUFDakIsU0FBaUMsRUFDakMsWUFBaUMsRUFDakMsTUFBYztRQUVkLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDdEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQztRQUNyRCxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQzVDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FB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