summaryrefslogtreecommitdiff
path: root/node_modules/babel-plugin-minify-replace/lib/index.js
blob: afc88a257e3f39a8f40b68fec55f92e8e55c7438 (plain)
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
"use strict";

module.exports = ({
  types: t
}) => {
  const NO_MEMBER = Symbol("no member");
  const replaceVisitor = {
    ReferencedIdentifier(path) {
      const _path = path,
            node = _path.node;
      const optionsMap = this.replacements[node.name];

      if (!optionsMap) {
        return;
      }

      let options;

      if (path.parentPath.isMemberExpression({
        object: node
      })) {
        const property = path.parent.property;
        const key = t.isIdentifier(property) && property.name;

        if (typeof key === "string") {
          options = optionsMap[key];
          path = path.parentPath;
        }
      }

      if (!options) {
        options = optionsMap[NO_MEMBER];
      }

      if (!options) {
        return;
      }

      path.replaceWith(options.node);
    }

  };
  return {
    name: "minify-replace",
    visitor: {
      Program(path) {
        /**
           Replacements is an array of objects like this:
           {
             identifierName: 'console',
             member: 'log', // optional
             replacement: {
               type: 'identifier',
               value: '',
             },
           }
        **/
        if (!this.opts.replacements) {
          // No replacements. Bail.
          return;
        }

        const map = Object.create(null);
        this.opts.replacements.forEach(({
          identifierName,
          replacement,
          member
        }) => {
          if (path.scope.globals[identifierName]) {
            // Convert to a node, we only allow identifiers and literals as replacements
            if (!replacement.type.match(/literal|identifier/i)) {
              throw new Error("Only literals and identifier are supported as replacements");
            }

            const node = t[replacement.type](replacement.value);
            const options = {
              identifierName,
              node,
              member
            };

            if (!map[identifierName]) {
              map[identifierName] = {};
            }

            if (member && map[identifierName][member]) {
              throw new Error(`Replacement collision ${identifierName}.${member}`);
            }

            map[identifierName][member || NO_MEMBER] = options;
          }
        });
        path.traverse(replaceVisitor, {
          replacements: map
        });
      }

    }
  };
};