UNPKG

2.82 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _postcss = require('postcss');
8
9var _postcss2 = _interopRequireDefault(_postcss);
10
11var _objectAssign = require('object-assign');
12
13var _objectAssign2 = _interopRequireDefault(_objectAssign);
14
15var _tcomb = require('tcomb');
16
17var _tcomb2 = _interopRequireDefault(_tcomb);
18
19function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
21var plugin = 'postcss-property-lookup';
22var lookupPattern = /@\(?([a-z-]+)\)?\b/g;
23
24var LogLevel = _tcomb2.default.enums.of(['error', 'warn'], 'LogLevel');
25var PluginOptions = _tcomb2.default.struct({
26 logLevel: LogLevel
27}, 'PluginOptions');
28
29var defaultOptions = {
30 logLevel: 'warn'
31};
32
33exports.default = _postcss2.default.plugin(plugin, propertyLookup);
34
35
36function propertyLookup(options) {
37 var _this = this;
38
39 var errorContext = { plugin };
40 options = new PluginOptions((0, _objectAssign2.default)({}, defaultOptions, options));
41
42 var log = {
43 warn(message, rule, result) {
44 rule.warn(result, message);
45 },
46 error(message, rule) {
47 throw rule.error(message, errorContext);
48 }
49 }[options.logLevel];
50
51 if (!log) {
52 throw new Error(`Invalid logLevel: ${options.logLevel}`);
53 }
54
55 return function (root, result) {
56 root.walkRules(function (rule) {
57 eachDecl(rule, function (decl) {
58 if (decl.value.indexOf('@') === -1) {
59 return;
60 }
61 decl.value = decl.value.replace(lookupPattern, resolveLookup.bind(_this, rule));
62 });
63 });
64
65 function resolveLookup(rule, orig, prop) {
66 var resolvedValue = closest(rule, prop);
67
68 if (!resolvedValue) {
69 log(`Unable to find property ${orig} in ${rule.selector}`, rule, result);
70 }
71
72 return resolvedValue;
73 }
74
75 function closest(container, prop) {
76 if (!container) {
77 return '';
78 }
79 var resolvedValue = void 0;
80
81 eachDecl(container, function (decl) {
82 if (decl.prop === prop) {
83 resolvedValue = decl.value;
84 }
85 });
86
87 // Ignore a reference to itself
88 // e.g a {color: @color;}
89 if (resolvedValue && resolvedValue.replace('@', '') === prop) {
90 return '';
91 }
92
93 if (!resolvedValue) {
94 return closest(container.parent, prop);
95 }
96
97 if (resolvedValue.indexOf('@') === -1) {
98 return resolvedValue;
99 }
100
101 return resolvedValue.replace(lookupPattern, resolveLookup.bind(this, container));
102 }
103 };
104}
105
106function eachDecl(container, callback) {
107 container.each(function (node) {
108 if (node.type === 'decl') {
109 callback(node);
110 }
111 // Recurse through child declarations of a media rule
112 if (node.type === 'atrule') {
113 eachDecl(node, callback);
114 }
115 });
116}
117module.exports = exports['default'];
\No newline at end of file