Skip to content

Commit 286ceba

Browse files
feat: PostCSS 8 (#10)
1 parent de45a53 commit 286ceba

File tree

7 files changed

+1504
-2141
lines changed

7 files changed

+1504
-2141
lines changed

.eslintrc

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,5 @@
55
"env": {
66
"node": true
77
},
8-
"rules": {
9-
"quotes": [2, "single"]
10-
}
8+
"extends": "eslint:recommended"
119
}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
.idea
2+
.nyc_output
13
node_modules
24
lib/

.travis.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
language: node_js
2+
23
node_js:
3-
- "6"
4-
- "8"
54
- "10"
65
- "12"
7-
script: npm run travis
6+
- "14"
7+
8+
script: yarn ci
89

910
after_success:
1011
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose

package.json

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
{
22
"name": "postcss-modules-values",
3-
"version": "3.0.0",
3+
"version": "4.0.0",
44
"description": "PostCSS plugin for CSS Modules to pass arbitrary values between your module files",
55
"main": "src/index.js",
66
"files": [
77
"src"
88
],
9+
"engines": {
10+
"node": ">= 10.13.0 || >= 12.13.0 || >= 14"
11+
},
912
"scripts": {
10-
"lint": "eslint src test",
11-
"pretest": "yarn lint",
13+
"prettier": "prettier -l --ignore-path .gitignore .",
14+
"eslint": "eslint --ignore-path .gitignore .",
15+
"pretest": "yarn eslint && yarn prettier",
1216
"test": "mocha",
1317
"autotest": "chokidar src test -c 'npm test'",
1418
"cover": "nyc mocha",
15-
"travis": "yarn lint && yarn cover",
19+
"ci": "yarn pretest && yarn cover",
1620
"prepublishOnly": "yarn test"
1721
},
1822
"repository": {
@@ -31,15 +35,19 @@
3135
},
3236
"homepage": "https://github.com/css-modules/postcss-modules-values#readme",
3337
"devDependencies": {
34-
"chokidar-cli": "^1.0.1",
35-
"codecov.io": "^0.1.2",
36-
"coveralls": "^3.0.2",
37-
"eslint": "^5.9.0",
38-
"mocha": "^6.1.4",
39-
"nyc": "^14.1.0"
38+
"chokidar-cli": "^2.1.0",
39+
"codecov.io": "^0.1.6",
40+
"coveralls": "^3.1.0",
41+
"eslint": "^7.9.0",
42+
"mocha": "^8.1.3",
43+
"nyc": "^15.1.0",
44+
"postcss": "^8.0.3",
45+
"prettier": "^2.1.2"
4046
},
4147
"dependencies": {
42-
"icss-utils": "^4.0.0",
43-
"postcss": "^7.0.6"
48+
"icss-utils": "^4.1.1"
49+
},
50+
"peerDependencies": {
51+
"postcss": "^8.0.3"
4452
}
4553
}

src/index.js

+119-102
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
'use strict';
1+
"use strict";
22

3-
const postcss = require('postcss');
4-
const ICSSUtils = require('icss-utils');
3+
const postcss = require("postcss");
4+
const ICSSUtils = require("icss-utils");
55

66
const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/;
77
const matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g;
@@ -12,107 +12,124 @@ let importIndex = 0;
1212
let createImportedName =
1313
(options && options.createImportedName) ||
1414
((importName /*, path*/) =>
15-
`i__const_${importName.replace(/\W/g, '_')}_${importIndex++}`);
16-
17-
module.exports = postcss.plugin(
18-
'postcss-modules-values',
19-
() => (css, result) => {
20-
const importAliases = [];
21-
const definitions = {};
22-
23-
const addDefinition = atRule => {
24-
let matches;
25-
while ((matches = matchValueDefinition.exec(atRule.params))) {
26-
let [, /*match*/ key, value] = matches;
27-
// Add to the definitions, knowing that values can refer to each other
28-
definitions[key] = ICSSUtils.replaceValueSymbols(value, definitions);
29-
atRule.remove();
30-
}
31-
};
32-
33-
const addImport = atRule => {
34-
const matches = matchImports.exec(atRule.params);
35-
if (matches) {
36-
let [, /*match*/ aliases, path] = matches;
37-
// We can use constants for path names
38-
if (definitions[path]) {
39-
path = definitions[path];
15+
`i__const_${importName.replace(/\W/g, "_")}_${importIndex++}`);
16+
17+
module.exports = () => {
18+
return {
19+
postcssPlugin: "postcss-modules-values",
20+
prepare(result) {
21+
const importAliases = [];
22+
const definitions = {};
23+
const addDefinition = (atRule) => {
24+
let matches;
25+
26+
while ((matches = matchValueDefinition.exec(atRule.params))) {
27+
let [, /*match*/ key, value] = matches;
28+
29+
// Add to the definitions, knowing that values can refer to each other
30+
definitions[key] = ICSSUtils.replaceValueSymbols(value, definitions);
31+
atRule.remove();
4032
}
41-
const imports = aliases
42-
.replace(/^\(\s*([\s\S]+)\s*\)$/, '$1')
43-
.split(/\s*,\s*/)
44-
.map(alias => {
45-
const tokens = matchImport.exec(alias);
46-
if (tokens) {
47-
const [, /*match*/ theirName, myName = theirName] = tokens;
48-
const importedName = createImportedName(myName);
49-
definitions[myName] = importedName;
50-
return { theirName, importedName };
33+
};
34+
const addImport = (atRule) => {
35+
const matches = matchImports.exec(atRule.params);
36+
37+
if (matches) {
38+
let [, /*match*/ aliases, path] = matches;
39+
40+
// We can use constants for path names
41+
if (definitions[path]) {
42+
path = definitions[path];
43+
}
44+
45+
const imports = aliases
46+
.replace(/^\(\s*([\s\S]+)\s*\)$/, "$1")
47+
.split(/\s*,\s*/)
48+
.map((alias) => {
49+
const tokens = matchImport.exec(alias);
50+
51+
if (tokens) {
52+
const [, /*match*/ theirName, myName = theirName] = tokens;
53+
const importedName = createImportedName(myName);
54+
definitions[myName] = importedName;
55+
return { theirName, importedName };
56+
} else {
57+
throw new Error(`@import statement "${alias}" is invalid!`);
58+
}
59+
});
60+
61+
importAliases.push({ path, imports });
62+
63+
atRule.remove();
64+
}
65+
};
66+
67+
return {
68+
/* Look at all the @value statements and treat them as locals or as imports */
69+
AtRule: {
70+
value(atRule) {
71+
if (matchImports.exec(atRule.params)) {
72+
addImport(atRule);
5173
} else {
52-
throw new Error(`@import statement "${alias}" is invalid!`);
74+
if (atRule.params.indexOf("@value") !== -1) {
75+
result.warn("Invalid value definition: " + atRule.params);
76+
}
77+
78+
addDefinition(atRule);
5379
}
80+
},
81+
},
82+
RootExit(root) {
83+
/* We want to export anything defined by now, but don't add it to the CSS yet or it well get picked up by the replacement stuff */
84+
const exportDeclarations = Object.keys(definitions).map((key) =>
85+
postcss.decl({
86+
value: definitions[key],
87+
prop: key,
88+
raws: { before: "\n " },
89+
})
90+
);
91+
92+
/* If we have no definitions, don't continue */
93+
if (!Object.keys(definitions).length) {
94+
return;
95+
}
96+
97+
/* Perform replacements */
98+
ICSSUtils.replaceSymbols(root, definitions);
99+
100+
/* Add export rules if any */
101+
if (exportDeclarations.length > 0) {
102+
const exportRule = postcss.rule({
103+
selector: ":export",
104+
raws: { after: "\n" },
105+
});
106+
107+
exportRule.append(exportDeclarations);
108+
109+
root.prepend(exportRule);
110+
}
111+
112+
/* Add import rules */
113+
importAliases.reverse().forEach(({ path, imports }) => {
114+
const importRule = postcss.rule({
115+
selector: `:import(${path})`,
116+
raws: { after: "\n" },
117+
});
118+
119+
imports.forEach(({ theirName, importedName }) => {
120+
importRule.append({
121+
value: theirName,
122+
prop: importedName,
123+
raws: { before: "\n " },
124+
});
125+
});
126+
127+
root.prepend(importRule);
54128
});
55-
importAliases.push({ path, imports });
56-
atRule.remove();
57-
}
58-
};
59-
60-
/* Look at all the @value statements and treat them as locals or as imports */
61-
css.walkAtRules('value', atRule => {
62-
if (matchImports.exec(atRule.params)) {
63-
addImport(atRule);
64-
} else {
65-
if (atRule.params.indexOf('@value') !== -1) {
66-
result.warn('Invalid value definition: ' + atRule.params);
67-
}
129+
},
130+
};
131+
},
132+
};
133+
};
68134

69-
addDefinition(atRule);
70-
}
71-
});
72-
73-
/* We want to export anything defined by now, but don't add it to the CSS yet or
74-
it well get picked up by the replacement stuff */
75-
const exportDeclarations = Object.keys(definitions).map(key =>
76-
postcss.decl({
77-
value: definitions[key],
78-
prop: key,
79-
raws: { before: '\n ' }
80-
})
81-
);
82-
83-
/* If we have no definitions, don't continue */
84-
if (!Object.keys(definitions).length) {
85-
return;
86-
}
87-
88-
/* Perform replacements */
89-
ICSSUtils.replaceSymbols(css, definitions);
90-
91-
/* Add export rules if any */
92-
if (exportDeclarations.length > 0) {
93-
const exportRule = postcss.rule({
94-
selector: ':export',
95-
raws: { after: '\n' }
96-
});
97-
exportRule.append(exportDeclarations);
98-
css.prepend(exportRule);
99-
}
100-
101-
/* Add import rules */
102-
importAliases.reverse().forEach(({ path, imports }) => {
103-
const importRule = postcss.rule({
104-
selector: `:import(${path})`,
105-
raws: { after: '\n' }
106-
});
107-
imports.forEach(({ theirName, importedName }) => {
108-
importRule.append({
109-
value: theirName,
110-
prop: importedName,
111-
raws: { before: '\n ' }
112-
});
113-
});
114-
115-
css.prepend(importRule);
116-
});
117-
}
118-
);
135+
module.exports.postcss = true;

0 commit comments

Comments
 (0)