Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

postcss-modules-scope

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss-modules-scope - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

181

lib/index.js

@@ -9,4 +9,2 @@ 'use strict';

function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { 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; } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }
var _postcss = require('postcss');

@@ -16,64 +14,138 @@

var localRegexp = /^\:local\(\.?([\w-]+)\)(\:\w+)?$/;
var _cssSelectorTokenizer = require('css-selector-tokenizer');
var processor = function processor(css) {
var exports = {};
var _cssSelectorTokenizer2 = _interopRequireDefault(_cssSelectorTokenizer);
// Find any :local classes
css.eachRule(function (rule) {
var match = rule.selector.match(localRegexp);
if (match) {
(function () {
var _match = _slicedToArray(match, 3);
function getSingleLocalNamesForComposes(selectors) {
return selectors.nodes.map(function (node) {
if (node.type !== 'selector' || node.nodes.length !== 1) {
throw new Error('composes 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('composes 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('composes 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('composes 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 exportedName = _match[1];
var pseudo = _match[2];
var processor = _postcss2['default'].plugin('postcss-modules-scope', function (options) {
return function (css) {
var generateScopedName = options && options.generateScopedName || processor.generateScopedName;
var scopedName = processor.generateScopedName(css.source.input.from, exportedName);
exports[exportedName] = exports[exportedName] || [];
if (exports[exportedName].indexOf(scopedName) === -1) {
exports[exportedName].push(scopedName);
}
rule.selector = '.' + scopedName + '' + (pseudo || '');
rule.eachDecl('composes', function (decl) {
var classes = decl.value.split(/ from /)[0];
exports[exportedName].push(classes);
decl.removeSelf();
});
})();
var exports = {};
function exportScopedName(name) {
var scopedName = generateScopedName(name, css.source.input.from);
exports[name] = exports[name] || [];
if (exports[name].indexOf(scopedName) < 0) {
exports[name].push(scopedName);
}
return scopedName;
}
});
// Find any :local keyframes
css.eachAtRule('keyframes', function (atRule) {
var match = atRule.params.match(localRegexp);
if (match) {
var _match2 = _slicedToArray(match, 2);
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');
}
var exportedName = _match2[1];
var scopedName = processor.generateScopedName(css.source.input.from, exportedName);
exports[exportedName] = exports[exportedName] || [];
exports[exportedName].push(scopedName);
atRule.params = scopedName;
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;
}
});
// If we found any :locals, insert an :export rule
var exportedNames = Object.keys(exports);
if (exportedNames.length > 0) {
css.prepend(_postcss2['default'].rule({
selector: ':export',
before: '\n',
nodes: exportedNames.map(function (exportedName) {
return _postcss2['default'].decl({
prop: exportedName,
value: exports[exportedName].join(' '),
before: '\n '
// Find any :local classes
css.eachRule(function (rule) {
var selector = _cssSelectorTokenizer2['default'].parse(rule.selector);
var newSelector = traverseNode(selector);
rule.selector = _cssSelectorTokenizer2['default'].stringify(newSelector);
rule.eachDecl('composes', function (decl) {
var localNames = getSingleLocalNamesForComposes(selector);
var classes = decl.value.split(/\s+/);
classes.forEach(function (className) {
localNames.forEach(function (exportedName) {
exports[exportedName].push(className);
});
});
})
}));
}
};
decl.removeSelf();
});
rule.eachDecl(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('');
});
});
processor.generateScopedName = function (path, exportedName) {
// Find any :local keyframes
css.eachAtRule(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) {
css.prepend(_postcss2['default'].rule({
selector: ':export',
nodes: exportedNames.map(function (exportedName) {
return _postcss2['default'].decl({
prop: exportedName,
value: exports[exportedName].join(' '),
before: '\n '
});
})
}));
}
};
});
processor.generateScopedName = function (exportedName, path) {
var sanitisedPath = path.replace(/\.[^\.\/\\]+$/, '').replace(/[\W_]+/g, '_').replace(/^_|_$/g, '');

@@ -84,3 +156,2 @@ return '_' + sanitisedPath + '__' + exportedName;

exports['default'] = processor;
module.exports = exports['default'];
/*match*/ /*match*/
module.exports = exports['default'];
{
"name": "postcss-modules-scope",
"version": "0.0.5",
"version": "0.0.6",
"description": "A CSS Modules transform to extract export statements from local-scope classes",

@@ -37,2 +37,3 @@ "main": "lib/index.js",

"dependencies": {
"css-selector-tokenizer": "^0.3.1",
"postcss": "^4.1.11"

@@ -39,0 +40,0 @@ },

@@ -43,3 +43,3 @@ # CSS Modules: Scope Locals & Extend

:local(.continueButton) {
extends: globalButtonStyle;
composes: globalButtonStyle;
color: green;

@@ -46,0 +46,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc