lepu-test-platform-web/node_modules/postcss-modules-scope/lib/index.js

183 lines
6.7 KiB
JavaScript
Raw Normal View History

'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _postcss = require('postcss');
var _postcss2 = _interopRequireDefault(_postcss);
var _cssSelectorTokenizer = require('css-selector-tokenizer');
var _cssSelectorTokenizer2 = _interopRequireDefault(_cssSelectorTokenizer);
var hasOwnProperty = Object.prototype.hasOwnProperty;
function getSingleLocalNamesForComposes(selectors) {
return selectors.nodes.map(function (node) {
if (node.type !== 'selector' || node.nodes.length !== 1) {
throw new Error('composition is only allowed when selector is single :local class name not in "' + _cssSelectorTokenizer2['default'].stringify(selectors) + '"');
}
node = node.nodes[0];
if (node.type !== 'nested-pseudo-class' || node.name !== 'local' || node.nodes.length !== 1) {
throw new Error('composition is only allowed when selector is single :local class name not in "' + _cssSelectorTokenizer2['default'].stringify(selectors) + '", "' + _cssSelectorTokenizer2['default'].stringify(node) + '" is weird');
}
node = node.nodes[0];
if (node.type !== 'selector' || node.nodes.length !== 1) {
throw new Error('composition is only allowed when selector is single :local class name not in "' + _cssSelectorTokenizer2['default'].stringify(selectors) + '", "' + _cssSelectorTokenizer2['default'].stringify(node) + '" is weird');
}
node = node.nodes[0];
if (node.type !== 'class') {
// 'id' is not possible, because you can't compose ids
throw new Error('composition is only allowed when selector is single :local class name not in "' + _cssSelectorTokenizer2['default'].stringify(selectors) + '", "' + _cssSelectorTokenizer2['default'].stringify(node) + '" is weird');
}
return node.name;
});
}
var processor = _postcss2['default'].plugin('postcss-modules-scope', function (options) {
return function (css) {
var generateScopedName = options && options.generateScopedName || processor.generateScopedName;
var exports = {};
function exportScopedName(name) {
var scopedName = generateScopedName(name, css.source.input.from, css.source.input.css);
exports[name] = exports[name] || [];
if (exports[name].indexOf(scopedName) < 0) {
exports[name].push(scopedName);
}
return scopedName;
}
function localizeNode(node) {
var newNode = Object.create(node);
switch (node.type) {
case 'selector':
newNode.nodes = node.nodes.map(localizeNode);
return newNode;
case 'class':
case 'id':
var scopedName = exportScopedName(node.name);
newNode.name = scopedName;
return newNode;
}
throw new Error(node.type + ' ("' + _cssSelectorTokenizer2['default'].stringify(node) + '") is not allowed in a :local block');
}
function traverseNode(node) {
switch (node.type) {
case 'nested-pseudo-class':
if (node.name === 'local') {
if (node.nodes.length !== 1) {
throw new Error('Unexpected comma (",") in :local block');
}
return localizeNode(node.nodes[0]);
}
/* falls through */
case 'selectors':
case 'selector':
var newNode = Object.create(node);
newNode.nodes = node.nodes.map(traverseNode);
return newNode;
}
return node;
}
// Find any :import and remember imported names
var importedNames = {};
css.walkRules(function (rule) {
if (/^:import\(.+\)$/.test(rule.selector)) {
rule.walkDecls(function (decl) {
importedNames[decl.prop] = true;
});
}
});
// Find any :local classes
css.walkRules(function (rule) {
var selector = _cssSelectorTokenizer2['default'].parse(rule.selector);
var newSelector = traverseNode(selector);
rule.selector = _cssSelectorTokenizer2['default'].stringify(newSelector);
rule.walkDecls(/composes|compose-with/, function (decl) {
var localNames = getSingleLocalNamesForComposes(selector);
var classes = decl.value.split(/\s+/);
classes.forEach(function (className) {
var global = /^global\(([^\)]+)\)$/.exec(className);
if (global) {
localNames.forEach(function (exportedName) {
exports[exportedName].push(global[1]);
});
} else if (hasOwnProperty.call(importedNames, className)) {
localNames.forEach(function (exportedName) {
exports[exportedName].push(className);
});
} else if (hasOwnProperty.call(exports, className)) {
localNames.forEach(function (exportedName) {
exports[className].forEach(function (item) {
exports[exportedName].push(item);
});
});
} else {
throw decl.error('referenced class name "' + className + '" in ' + decl.prop + ' not found');
}
});
decl.remove();
});
rule.walkDecls(function (decl) {
var tokens = decl.value.split(/(,|'[^']*'|"[^"]*")/);
tokens = tokens.map(function (token, idx) {
if (idx === 0 || tokens[idx - 1] === ',') {
var localMatch = /^(\s*):local\s*\((.+?)\)/.exec(token);
if (localMatch) {
return localMatch[1] + exportScopedName(localMatch[2]) + token.substr(localMatch[0].length);
} else {
return token;
}
} else {
return token;
}
});
decl.value = tokens.join('');
});
});
// Find any :local keyframes
css.walkAtRules(function (atrule) {
if (/keyframes$/.test(atrule.name)) {
var localMatch = /^\s*:local\s*\((.+?)\)\s*$/.exec(atrule.params);
if (localMatch) {
atrule.params = exportScopedName(localMatch[1]);
}
}
});
// If we found any :locals, insert an :export rule
var exportedNames = Object.keys(exports);
if (exportedNames.length > 0) {
(function () {
var exportRule = _postcss2['default'].rule({ selector: ':export' });
exportedNames.forEach(function (exportedName) {
return exportRule.append({
prop: exportedName,
value: exports[exportedName].join(' '),
raws: { before: '\n ' }
});
});
css.append(exportRule);
})();
}
};
});
processor.generateScopedName = function (exportedName, path) {
var sanitisedPath = path.replace(/\.[^\.\/\\]+$/, '').replace(/[\W_]+/g, '_').replace(/^_|_$/g, '');
return '_' + sanitisedPath + '__' + exportedName;
};
exports['default'] = processor;
module.exports = exports['default'];