@notiv/postcss-property-lookup
Version:
PostCSS plugin that allows referencing property values without a variable
129 lines (100 loc) • 4.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _tcomb = _interopRequireDefault(require("tcomb"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var plugin = 'postcss-property-lookup';
var LogLevel = _tcomb["default"].enums.of(['error', 'warn'], 'LogLevel');
var PluginOptions = _tcomb["default"].struct({
logLevel: LogLevel,
lookupPattern: _tcomb["default"].Re,
skipUnknown: _tcomb["default"].Boolean
}, 'PluginOptions');
var defaultOptions = {
logLevel: 'warn',
lookupPattern: /@\(?([a-z-]+)\)?\b/g,
skipUnknown: true
};
var _default = propertyLookup;
exports["default"] = _default;
propertyLookup.postcss = true;
function propertyLookup(options) {
var errorContext = {
plugin: plugin
};
options = new PluginOptions(_objectSpread(_objectSpread({}, defaultOptions), options));
var log = {
warn: function warn(message, rule, result) {
rule.warn(result, message);
},
error: function error(message, rule) {
throw rule.error(message, errorContext);
}
}[options.logLevel];
if (!log) {
throw new Error("Invalid logLevel: ".concat(options.logLevel));
}
return {
postcssPlugin: plugin,
Root: function Root(root, _ref) {
var _this = this;
var result = _ref.result;
root.walkRules(function (rule) {
eachDecl(rule, function (decl) {
if (decl.value.indexOf('@') === -1) {
return;
}
decl.value = decl.value.replace(options.lookupPattern, resolveLookup.bind(_this, rule));
});
});
function resolveLookup(rule, orig, prop) {
var resolvedValue = closest(rule, prop);
if (!resolvedValue) {
if (options.skipUnknown) {
return orig;
}
log("Unable to find property ".concat(orig, " in ").concat(rule.selector), rule, result);
}
return resolvedValue;
}
function closest(container, prop) {
if (!container) {
return '';
}
var resolvedValue;
eachDecl(container, function (decl) {
if (decl.prop === prop) {
resolvedValue = decl.value;
}
});
if (!resolvedValue) {
return closest(container.parent, prop);
} // Ignore a reference to itself
// e.g a {color: @color;}
if (resolvedValue && resolvedValue.replace('@', '') === prop) {
// Lookup on parent the same property
return closest(container.parent, prop); // return '';
}
if (resolvedValue.indexOf('@') === -1) {
return resolvedValue;
}
return resolvedValue.replace(options.lookupPattern, resolveLookup.bind(this, container));
}
}
};
}
function eachDecl(container, callback) {
container.each(function (node) {
if (node.type === 'decl') {
callback(node);
} // Recurse through child declarations of a media rule
if (node.type === 'atrule') {
eachDecl(node, callback);
}
});
}