postcss-use
Version:
Enable PostCSS plugins directly in your stylesheet.
198 lines (160 loc) • 7.54 kB
JavaScript
;
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 _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _postcss = require('postcss');
var _postcss2 = _interopRequireDefault(_postcss);
var _resolveFrom = require('resolve-from');
var _resolveFrom2 = _interopRequireDefault(_resolveFrom);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var useParamsRegExp = /^([^\(\s]+)(?:\s*\(\s*([\W\w]+)\s*\))?/;
var optionRegExp = /^\s*([\W\w]+?)\s*:\s*([\W\w]+)\s*$/;
exports.default = _postcss2.default.plugin('postcss-use', function (opts) {
// options
var _Object = Object(opts),
_Object$modules = _Object.modules,
modules = _Object$modules === undefined ? [] : _Object$modules,
_Object$options = _Object.options,
options = _Object$options === undefined ? {} : _Object$options,
_Object$resolveFromFi = _Object.resolveFromFile,
resolveFromFile = _Object$resolveFromFi === undefined ? false : _Object$resolveFromFi;
return function (root, result) {
// preserved plugins list
var preservedPlugins = result.processor.plugins.slice();
// walk @use rules
root.walkAtRules('use', function (rule) {
// match plugin and plugin params
var paramsMatch = rule.params.match(useParamsRegExp);
if (paramsMatch) {
var _paramsMatch = _slicedToArray(paramsMatch, 3),
pluginName = _paramsMatch[1],
_paramsMatch$ = _paramsMatch[2],
pluginParams = _paramsMatch$ === undefined ? '' : _paramsMatch$;
// whether the plugin is whitelisted
var isAllowablePlugin = [].concat(modules).some(function (mod) {
return typeof mod === 'string' ? mod === '*' || mod === pluginName : pluginName.match(mod);
});
if (isAllowablePlugin) {
// plugin options
var defaultOpts = Object(options)[pluginName];
var paramOpts = getOptionsFromParams(pluginParams);
var childOpts = getOptionsFromRuleChildren(rule);
var pluginOpts = defaultOpts === undefined && Array.isArray(paramOpts) ? paramOpts : Object.assign({}, defaultOpts, paramOpts, childOpts);
try {
// add plugin to plugins list
var pluginPath = resolveFromFile && rule.source.input.file ? (0, _resolveFrom2.default)(_path2.default.dirname(rule.source.input.file), pluginName) : pluginName;
var plugin = require(pluginPath)(pluginOpts);
result.processor.plugins.push(plugin);
} catch (error) {
throw new Error('Cannot find module \'' + pluginName + '\'');
}
} else {
throw new ReferenceError('\'' + pluginName + '\' is not a valid PostCSS plugin.');
}
}
rule.remove();
});
result.processor.plugins.push(_postcss2.default.plugin('postcss-use#reset', function () {
return function () {
// restore preserved plugins list
result.processor.plugins = preservedPlugins;
};
})());
};
});
// get options from params using functional notation
function getOptionsFromParams(params) {
try {
// as json
return JSON.parse(params);
} catch (error) {
// as properties, split as declarations
var options = {};
var decls = _postcss2.default.list.comma(params);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = decls[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var decl = _step.value;
if (decl) {
var declMatch = decl.match(optionRegExp);
if (declMatch) {
var _declMatch = _slicedToArray(declMatch, 3),
property = _declMatch[1],
value = _declMatch[2];
try {
options[property] = JSON.parse(value);
} catch (error2) {
options[property] = value;
}
} else {
throw new SyntaxError('Options must include a property and value');
}
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return options;
}
}
// get options from rule childrem
function getOptionsFromRuleChildren(rule) {
var options = {};
if (rule.nodes) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = rule.nodes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var node = _step2.value;
var prop = node.prop,
selector = node.selector,
type = node.type,
value = node.value;
if (type === 'decl') {
try {
// as json
options[prop] = JSON.parse(value);
} catch (error) {
// as a string
options[prop] = value;
}
} else if (type === 'rule') {
// as nested options
options[selector] = getOptionsFromRuleChildren(node);
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
return options;
}
module.exports = exports['default'];