• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FullHuman / purgecss / 4851732933

01 May 2023 02:00PM CUT coverage: 86.679%. Remained the same
4851732933

Pull #1107

github

GitHub
Merge d4daf2632 into 152ccba46
Pull Request #1107: build(deps-dev): bump grunt from 1.5.3 to 1.6.1

317 of 372 branches covered (85.22%)

Branch coverage included in aggregate %.

145 of 161 relevant lines covered (90.06%)

333.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.0
/packages/purgecss/src/VariablesStructure.ts
1
import * as postcss from "postcss";
2
import { StringRegExpArray } from "./types";
3

4
/**
5
 * @public
6
 */
7
export class VariableNode {
22✔
8
  public nodes: VariableNode[] = [];
30✔
9
  public value: postcss.Declaration;
10
  public isUsed = false;
30✔
11

12
  constructor(declaration: postcss.Declaration) {
13
    this.value = declaration;
30✔
14
  }
15
}
16

17
/**
18
 * @public
19
 */
20
export class VariablesStructure {
22✔
21
  public nodes: Map<string, VariableNode[]> = new Map();
52✔
22
  public usedVariables: Set<string> = new Set();
52✔
23
  public safelist: StringRegExpArray = [];
52✔
24

25
  addVariable(declaration: postcss.Declaration): void {
26
    const { prop } = declaration;
30✔
27
    if (!this.nodes.has(prop)) {
30✔
28
      const node = new VariableNode(declaration);
19✔
29
      this.nodes.set(prop, [node]);
19✔
30
    } else {
31
      const node = new VariableNode(declaration);
11✔
32
      const variableNodes = this.nodes.get(prop) || [];
11!
33
      this.nodes.set(prop, [...variableNodes, node]);
11✔
34
    }
35
  }
36

37
  addVariableUsage(
38
    declaration: postcss.Declaration,
39
    matchedVariables: IterableIterator<RegExpMatchArray>
40
  ): void {
41
    const { prop } = declaration;
30✔
42
    const nodes = this.nodes.get(prop);
30✔
43
    for (const variableMatch of matchedVariables) {
30✔
44
      // capturing group containing the variable is in index 1
45
      const variableName = variableMatch[1];
13✔
46
      if (this.nodes.has(variableName)) {
13✔
47
        const usedVariableNodes = this.nodes.get(variableName);
10✔
48
        nodes?.forEach((node) => {
10!
49
          usedVariableNodes?.forEach((usedVariableNode) =>
14!
50
            node.nodes.push(usedVariableNode)
20✔
51
          );
52
        });
53
      }
54
    }
55
  }
56

57
  addVariableUsageInProperties(
58
    matchedVariables: IterableIterator<RegExpMatchArray>
59
  ): void {
60
    for (const variableMatch of matchedVariables) {
17✔
61
      // capturing group containing the variable is in index 1
62
      const variableName = variableMatch[1];
17✔
63
      this.usedVariables.add(variableName);
17✔
64
    }
65
  }
66

67
  setAsUsed(variableName: string): void {
68
    const nodes = this.nodes.get(variableName);
12✔
69
    if (nodes) {
12✔
70
      const queue = [...nodes];
12✔
71
      while (queue.length !== 0) {
12✔
72
        const currentNode = queue.pop();
33✔
73
        if (currentNode && !currentNode.isUsed) {
33✔
74
          currentNode.isUsed = true;
19✔
75
          queue.push(...currentNode.nodes);
19✔
76
        }
77
      }
78
    }
79
  }
80

81
  removeUnused(): void {
82
    // check unordered usage
83
    for (const used of this.usedVariables) {
2✔
84
      const usedNodes = this.nodes.get(used);
12✔
85
      if (usedNodes) {
12✔
86
        for (const usedNode of usedNodes) {
12✔
87
          const usedVariablesMatchesInDeclaration =
88
            usedNode.value.value.matchAll(/var\((.+?)[,)]/g);
19✔
89

90
          for (const usage of usedVariablesMatchesInDeclaration) {
19✔
91
            if (!this.usedVariables.has(usage[1])) {
8✔
92
              this.usedVariables.add(usage[1]);
5✔
93
            }
94
          }
95
        }
96
      }
97
    }
98

99
    for (const used of this.usedVariables) {
2✔
100
      this.setAsUsed(used);
12✔
101
    }
102

103
    for (const [name, declarations] of this.nodes) {
2✔
104
      for (const declaration of declarations) {
19✔
105
        if (!declaration.isUsed && !this.isVariablesSafelisted(name)) {
30✔
106
          declaration.value.remove();
9✔
107
        }
108
      }
109
    }
110
  }
111

112
  isVariablesSafelisted(variable: string): boolean {
113
    return this.safelist.some((safelistItem) => {
11✔
114
      return typeof safelistItem === "string"
5✔
115
        ? safelistItem === variable
116
        : safelistItem.test(variable);
117
    });
118
  }
119
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc