Skip to content

Commit

Permalink
chore(deps): update
Browse files Browse the repository at this point in the history
chore(deps): update
  • Loading branch information
evilebottnawi committed Nov 23, 2018
2 parents 68affb4 + 652d61f commit 41f5b08
Show file tree
Hide file tree
Showing 7 changed files with 3,001 additions and 127 deletions.
21 changes: 3 additions & 18 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2018
},
"env": {
"node": true
},
"ecmaFeatures": {
"arrowFunctions": true,
"blockBindings": true,
"classes": true,
"defaultParams": true,
"destructuring": true,
"forOf": true,
"modules": true,
"objectLiteralComputedProperties": true,
"objectLiteralShorthandMethods": true,
"objectLiteralShorthandProperties": true,
"spread": true,
"superInFunctions": true,
"templateStrings": true,
"unicodeCodePointEscapes": true,
"jsx": true
},
"rules": {
"quotes": [2, "single"]
}
Expand Down
8 changes: 3 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
language: node_js
node_js:
- "4"
- "6"
- "node"
- "8"
- "10"
- "11"
script: npm run travis

before_install:
- '[ "${TRAVIS_NODE_VERSION}" != "0.10" ] || npm install -g npm'

after_success:
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose
- cat ./coverage/coverage.json | node_modules/codecov.io/bin/codecov.io.js
Expand Down
40 changes: 19 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
{
"name": "postcss-modules-scope",
"version": "1.1.0",
"version": "2.0.0",
"description": "A CSS Modules transform to extract export statements from local-scope classes",
"main": "lib/index.js",
"main": "src/index.js",
"engines": {
"node": ">= 6"
},
"scripts": {
"lint": "eslint src",
"build": "babel --out-dir lib src",
"watch": "chokidar src -c 'npm run build'",
"test": "mocha --compilers js:babel/register",
"posttest": "npm run lint && npm run build",
"autotest": "chokidar src test -c 'npm test'",
"precover": "npm run lint && npm run build",
"cover": "babel-istanbul cover node_modules/.bin/_mocha",
"travis": "npm run cover -- --report lcovonly",
"prepublish": "npm run build"
"lint": "eslint src test",
"pretest": "yarn lint",
"test": "mocha",
"autotest": "chokidar src test -c 'yarn test'",
"precover": "yarn lint",
"cover": "nyc mocha",
"travis": "yarn cover",
"prepublish": "yarn run test"
},
"repository": {
"type": "git",
Expand All @@ -25,7 +26,7 @@
"plugin"
],
"files": [
"lib"
"src"
],
"author": "Glen Maddern",
"license": "ISC",
Expand All @@ -35,18 +36,15 @@
"homepage": "https://github.com/css-modules/postcss-modules-scope",
"dependencies": {
"css-selector-tokenizer": "^0.7.0",
"postcss": "^6.0.1"
"postcss": "^7.0.6"
},
"devDependencies": {
"babel": "^5.4.7",
"babel-eslint": "^6.1.2",
"babel-istanbul": "^0.4.0",
"babelify": "^7.1.0",
"chokidar-cli": "^1.0.1",
"codecov.io": "^0.1.2",
"coveralls": "^2.11.2",
"coveralls": "^3.0.2",
"css-selector-parser": "^1.0.4",
"eslint": "^1.5.0",
"mocha": "^3.0.1"
"eslint": "^5.9.0",
"nyc": "^13.1.0",
"mocha": "^5.2.0"
}
}
161 changes: 103 additions & 58 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,86 +1,122 @@
import postcss from 'postcss';
import Tokenizer from 'css-selector-tokenizer';
'use strict';

let hasOwnProperty = Object.prototype.hasOwnProperty;
const postcss = require('postcss');
const Tokenizer = require('css-selector-tokenizer');

const hasOwnProperty = Object.prototype.hasOwnProperty;

function getSingleLocalNamesForComposes(selectors) {
return selectors.nodes.map((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 "' +
Tokenizer.stringify(selectors) + '"');
return selectors.nodes.map(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 "' +
Tokenizer.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 "' +
Tokenizer.stringify(selectors) + '", "' + Tokenizer.stringify(node) + '" is weird');
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 "' +
Tokenizer.stringify(selectors) +
'", "' +
Tokenizer.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 "' +
Tokenizer.stringify(selectors) + '", "' + Tokenizer.stringify(node) + '" is weird');
if (node.type !== 'selector' || node.nodes.length !== 1) {
throw new Error(
'composition is only allowed when selector is single :local class name not in "' +
Tokenizer.stringify(selectors) +
'", "' +
Tokenizer.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 "' +
Tokenizer.stringify(selectors) + '", "' + Tokenizer.stringify(node) + '" is weird');
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 "' +
Tokenizer.stringify(selectors) +
'", "' +
Tokenizer.stringify(node) +
'" is weird'
);
}
return node.name;
});
}

const processor = postcss.plugin('postcss-modules-scope', function(options) {
return (css) => {
let generateScopedName = options && options.generateScopedName || processor.generateScopedName;
return css => {
const generateScopedName =
(options && options.generateScopedName) || processor.generateScopedName;

let exports = {};
const exports = {};

function exportScopedName(name) {
let scopedName = generateScopedName(name, css.source.input.from, css.source.input.css);
const scopedName = generateScopedName(
name,
css.source.input.from,
css.source.input.css
);
exports[name] = exports[name] || [];
if(exports[name].indexOf(scopedName) < 0) {
if (exports[name].indexOf(scopedName) < 0) {
exports[name].push(scopedName);
}
return scopedName;
}

function localizeNode(node) {
let newNode = Object.create(node);
switch(node.type) {
const newNode = Object.create(node);
switch (node.type) {
case 'selector':
newNode.nodes = node.nodes.map(localizeNode);
return newNode;
case 'class':
case 'id':
let scopedName = exportScopedName(node.name);
newNode.name = scopedName;
case 'id': {
newNode.name = exportScopedName(node.name);
return newNode;
}
}
throw new Error(node.type + ' ("' + Tokenizer.stringify(node) + '") is not allowed in a :local block');
throw new Error(
node.type +
' ("' +
Tokenizer.stringify(node) +
'") is not allowed in a :local block'
);
}

function traverseNode(node) {
switch(node.type) {
switch (node.type) {
case 'nested-pseudo-class':
if(node.name === 'local') {
if(node.nodes.length !== 1) {
if (node.name === 'local') {
if (node.nodes.length !== 1) {
throw new Error('Unexpected comma (",") in :local block');
}
return localizeNode(node.nodes[0]);
}
/* falls through */
/* falls through */
case 'selectors':
case 'selector':
let newNode = Object.create(node);
case 'selector': {
const newNode = Object.create(node);
newNode.nodes = node.nodes.map(traverseNode);
return newNode;
}
}
return node;
}

// Find any :import and remember imported names
let importedNames = {};
const importedNames = {};
css.walkRules(rule => {
if(/^:import\(.+\)$/.test(rule.selector)) {
if (/^:import\(.+\)$/.test(rule.selector)) {
rule.walkDecls(decl => {
importedNames[decl.prop] = true;
});
Expand All @@ -89,30 +125,32 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {

// Find any :local classes
css.walkRules(rule => {
let selector = Tokenizer.parse(rule.selector);
let newSelector = traverseNode(selector);
const selector = Tokenizer.parse(rule.selector);
const newSelector = traverseNode(selector);
rule.selector = Tokenizer.stringify(newSelector);
rule.walkDecls(/composes|compose-with/, decl => {
let localNames = getSingleLocalNamesForComposes(selector);
let classes = decl.value.split(/\s+/);
classes.forEach((className) => {
let global = /^global\(([^\)]+)\)$/.exec(className);
const localNames = getSingleLocalNamesForComposes(selector);
const classes = decl.value.split(/\s+/);
classes.forEach(className => {
const global = /^global\(([^\)]+)\)$/.exec(className);
if (global) {
localNames.forEach((exportedName) => {
localNames.forEach(exportedName => {
exports[exportedName].push(global[1]);
})
});
} else if (hasOwnProperty.call(importedNames, className)) {
localNames.forEach((exportedName) => {
localNames.forEach(exportedName => {
exports[exportedName].push(className);
});
} else if (hasOwnProperty.call(exports, className)) {
localNames.forEach((exportedName) => {
exports[className].forEach((item) => {
localNames.forEach(exportedName => {
exports[className].forEach(item => {
exports[exportedName].push(item);
});
});
} else {
throw decl.error(`referenced class name "${className}" in ${decl.prop} not found`);
throw decl.error(
`referenced class name "${className}" in ${decl.prop} not found`
);
}
});
decl.remove();
Expand All @@ -121,10 +159,14 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
rule.walkDecls(decl => {
var tokens = decl.value.split(/(,|'[^']*'|"[^"]*")/);
tokens = tokens.map((token, idx) => {
if(idx === 0 || tokens[idx - 1] === ',') {
let localMatch = /^(\s*):local\s*\((.+?)\)/.exec(token);
if(localMatch) {
return localMatch[1] + exportScopedName(localMatch[2]) + token.substr(localMatch[0].length);
if (idx === 0 || tokens[idx - 1] === ',') {
const localMatch = /^(\s*):local\s*\((.+?)\)/.exec(token);
if (localMatch) {
return (
localMatch[1] +
exportScopedName(localMatch[2]) +
token.substr(localMatch[0].length)
);
} else {
return token;
}
Expand All @@ -138,19 +180,19 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {

// Find any :local keyframes
css.walkAtRules(atrule => {
if(/keyframes$/.test(atrule.name)) {
if (/keyframes$/i.test(atrule.name)) {
var localMatch = /^\s*:local\s*\((.+?)\)\s*$/.exec(atrule.params);
if(localMatch) {
if (localMatch) {
atrule.params = exportScopedName(localMatch[1]);
}
}
});

// If we found any :locals, insert an :export rule
let exportedNames = Object.keys(exports);
const exportedNames = Object.keys(exports);
if (exportedNames.length > 0) {
let exportRule = postcss.rule({selector: `:export`});
exportedNames.forEach(exportedName =>
const exportRule = postcss.rule({ selector: ':export' });
exportedNames.forEach(exportedName =>
exportRule.append({
prop: exportedName,
value: exports[exportedName].join(' '),
Expand All @@ -163,8 +205,11 @@ const processor = postcss.plugin('postcss-modules-scope', function(options) {
});

processor.generateScopedName = function(exportedName, path) {
let sanitisedPath = path.replace(/\.[^\.\/\\]+$/, '').replace(/[\W_]+/g, '_').replace(/^_|_$/g, '');
const sanitisedPath = path
.replace(/\.[^\.\/\\]+$/, '')
.replace(/[\W_]+/g, '_')
.replace(/^_|_$/g, '');
return `_${sanitisedPath}__${exportedName}`;
};

export default processor;
module.exports = processor;
Loading

0 comments on commit 41f5b08

Please sign in to comment.