index.js 5.07 KB
Newer Older
Patrick's avatar
Patrick committed
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
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _postcss = require('postcss');

var _postcss2 = _interopRequireDefault(_postcss);

var _icssReplaceSymbols = require('icss-replace-symbols');

var _icssReplaceSymbols2 = _interopRequireDefault(_icssReplaceSymbols);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/;
var matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g;
var matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/;
var options = {};
var importIndex = 0;
var createImportedName = options && options.createImportedName || function (importName /*, path*/) {
  return 'i__const_' + importName.replace(/\W/g, '_') + '_' + importIndex++;
};

exports.default = _postcss2.default.plugin('postcss-modules-values', function () {
  return function (css, result) {
    var importAliases = [];
    var definitions = {};

    var addDefinition = function addDefinition(atRule) {
      var matches = void 0;
      while (matches = matchValueDefinition.exec(atRule.params)) {
        var _matches = matches;

        var _matches2 = _slicedToArray(_matches, 3);

        var /*match*/key = _matches2[1];
        var value = _matches2[2];
        // Add to the definitions, knowing that values can refer to each other

        definitions[key] = (0, _icssReplaceSymbols.replaceAll)(definitions, value);
        atRule.remove();
      }
    };

    var addImport = function addImport(atRule) {
      var matches = matchImports.exec(atRule.params);
      if (matches) {
        var _matches3 = _slicedToArray(matches, 3);

        var /*match*/aliases = _matches3[1];
        var path = _matches3[2];
        // We can use constants for path names

        if (definitions[path]) path = definitions[path];
        var imports = aliases.replace(/^\(\s*([\s\S]+)\s*\)$/, '$1').split(/\s*,\s*/).map(function (alias) {
          var tokens = matchImport.exec(alias);
          if (tokens) {
            var _tokens = _slicedToArray(tokens, 3);

            var /*match*/theirName = _tokens[1];
            var _tokens$ = _tokens[2];
            var myName = _tokens$ === undefined ? theirName : _tokens$;

            var importedName = createImportedName(myName);
            definitions[myName] = importedName;
            return { theirName: theirName, importedName: importedName };
          } else {
            throw new Error('@import statement "' + alias + '" is invalid!');
          }
        });
        importAliases.push({ path: path, imports: imports });
        atRule.remove();
      }
    };

    /* Look at all the @value statements and treat them as locals or as imports */
    css.walkAtRules('value', function (atRule) {
      if (matchImports.exec(atRule.params)) {
        addImport(atRule);
      } else {
        if (atRule.params.indexOf('@value') !== -1) {
          result.warn('Invalid value definition: ' + atRule.params);
        }

        addDefinition(atRule);
      }
    });

    /* We want to export anything defined by now, but don't add it to the CSS yet or
     it well get picked up by the replacement stuff */
    var exportDeclarations = Object.keys(definitions).map(function (key) {
      return _postcss2.default.decl({
        value: definitions[key],
        prop: key,
        raws: { before: "\n  " }
      });
    });

    /* If we have no definitions, don't continue */
    if (!Object.keys(definitions).length) return;

    /* Perform replacements */
    (0, _icssReplaceSymbols2.default)(css, definitions);

    /* Add export rules if any */
    if (exportDeclarations.length > 0) {
      var exportRule = _postcss2.default.rule({
        selector: ':export',
        raws: { after: "\n" }
      });
      exportRule.append(exportDeclarations);
      css.prepend(exportRule);
    }

    /* Add import rules */
    importAliases.reverse().forEach(function (_ref) {
      var path = _ref.path;
      var imports = _ref.imports;

      var importRule = _postcss2.default.rule({
        selector: ':import(' + path + ')',
        raws: { after: "\n" }
      });
      imports.forEach(function (_ref2) {
        var theirName = _ref2.theirName;
        var importedName = _ref2.importedName;

        importRule.append({
          value: theirName,
          prop: importedName,
          raws: { before: "\n  " }
        });
      });

      css.prepend(importRule);
    });
  };
});
module.exports = exports['default'];