Skip to content

Commit 89cdbb1

Browse files
refactor: code
2 parents f17f368 + f45bfba commit 89cdbb1

File tree

6 files changed

+567
-530
lines changed

6 files changed

+567
-530
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"node": true,
88
"jest": true
99
},
10-
"extends": "eslint:recommended"
10+
"extends": ["eslint:recommended", "prettier"]
1111
}

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@
33
All notable changes to this project will be documented in this file.
44
This project adheres to [Semantic Versioning](http://semver.org/).
55

6+
## [3.0.0-rc.3](https://github.com/postcss-modules-local-by-default/compare/v3.0.0-rc.2...v3.0.0-rc.3) - 2020-11-08
7+
8+
### Fixes
9+
10+
- broken release
11+
12+
## [3.0.0-rc.2](https://github.com/postcss-modules-local-by-default/compare/v3.0.0-rc.1...v3.0.0-rc.2) - 2020-10-08
13+
14+
### BREAKING CHANGE
15+
16+
- minimum supported `postcss` version is `^8.1.0`
17+
18+
### Fixes
19+
20+
- minimum supported `Node.js` version is `^10 || ^12 || >= 14`
21+
- compatibility with other plugins
22+
- compatibility with PostCSS 8
23+
624
## [3.0.0-rc.1](https://github.com/postcss-modules-local-by-default/compare/v3.0.0-rc.0...v3.0.0-rc.1) - 2020-09-18
725

826
### Fixes

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "postcss-modules-extract-imports",
3-
"version": "3.0.0-rc.1",
3+
"version": "3.0.0-rc.3",
44
"description": "A CSS Modules transform to extract local aliases for inline imports",
55
"main": "src/index.js",
66
"engines": {
7-
"node": ">= 10.13.0 || >= 12.13.0 || >= 14"
7+
"node": "^10 || ^12 || >= 14"
88
},
99
"files": [
1010
"src"
@@ -37,14 +37,15 @@
3737
"homepage": "https://github.com/css-modules/postcss-modules-extract-imports",
3838
"devDependencies": {
3939
"coveralls": "^3.1.0",
40-
"eslint": "^7.9.0",
40+
"eslint": "^7.10.0",
41+
"eslint-config-prettier": "^6.12.0",
4142
"husky": "^4.3.0",
42-
"jest": "^26.4.2",
43+
"jest": "^26.5.2",
4344
"lint-staged": "^10.4.0",
44-
"postcss": "^8.0.7",
45+
"postcss": "^8.1.1",
4546
"prettier": "^2.1.2"
4647
},
4748
"peerDependencies": {
48-
"postcss": "^8.0.0"
49+
"postcss": "^8.1.0"
4950
}
5051
}

src/index.js

Lines changed: 122 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
const topologicalSort = require("./topologicalSort");
22

3-
const declWhitelist = ["composes"];
4-
const declFilter = new RegExp(`^(${declWhitelist.join("|")})$`);
53
const matchImports = /^(.+?)\s+from\s+(?:"([^"]+)"|'([^']+)'|(global))$/;
64
const icssImport = /^:import\((?:"([^"]+)"|'([^']+)')\)/;
75

86
const VISITED_MARKER = 1;
97

10-
function createParentName(rule, root) {
11-
return `__${root.index(rule.parent)}_${rule.selector}`;
12-
}
13-
14-
function serializeImports(imports) {
15-
return imports.map((importPath) => "`" + importPath + "`").join(", ");
16-
}
17-
188
/**
199
* :import('G') {}
2010
*
@@ -54,139 +44,155 @@ function addImportToGraph(importId, parentId, graph, visited) {
5444
}
5545

5646
visited[visitedId] = VISITED_MARKER;
47+
5748
siblings.push(importId);
5849
}
5950
}
6051

6152
module.exports = (options = {}) => {
53+
let importIndex = 0;
54+
const createImportedName =
55+
typeof options.createImportedName !== "function"
56+
? (importName /*, path*/) =>
57+
`i__imported_${importName.replace(/\W/g, "_")}_${importIndex++}`
58+
: options.createImportedName;
6259
const failOnWrongOrder = options.failOnWrongOrder;
6360

6461
return {
6562
postcssPlugin: "postcss-modules-extract-imports",
66-
RootExit(root, postcss) {
63+
prepare() {
6764
const graph = {};
6865
const visited = {};
69-
7066
const existingImports = {};
7167
const importDecls = {};
7268
const imports = {};
7369

74-
let importIndex = 0;
75-
76-
const createImportedName =
77-
typeof options.createImportedName !== "function"
78-
? (importName /*, path*/) =>
79-
`i__imported_${importName.replace(/\W/g, "_")}_${importIndex++}`
80-
: options.createImportedName;
81-
82-
// Check the existing imports order and save refs
83-
root.walkRules((rule) => {
84-
const matches = icssImport.exec(rule.selector);
85-
86-
if (matches) {
87-
const [, /*match*/ doubleQuotePath, singleQuotePath] = matches;
88-
const importPath = doubleQuotePath || singleQuotePath;
89-
90-
addImportToGraph(importPath, "root", graph, visited);
91-
92-
existingImports[importPath] = rule;
93-
}
94-
});
95-
96-
// Find any declaration that supports imports
97-
root.walkDecls(declFilter, (decl) => {
98-
let matches = decl.value.match(matchImports);
99-
let tmpSymbols;
100-
101-
if (matches) {
102-
let [
103-
,
104-
/*match*/ symbols,
105-
doubleQuotePath,
106-
singleQuotePath,
107-
global,
108-
] = matches;
109-
110-
if (global) {
111-
// Composing globals simply means changing these classes to wrap them in global(name)
112-
tmpSymbols = symbols.split(/\s+/).map((s) => `global(${s})`);
113-
} else {
114-
const importPath = doubleQuotePath || singleQuotePath;
115-
const parentRule = createParentName(decl.parent, root);
116-
117-
addImportToGraph(importPath, parentRule, graph, visited);
118-
119-
importDecls[importPath] = decl;
120-
imports[importPath] = imports[importPath] || {};
121-
122-
tmpSymbols = symbols.split(/\s+/).map((s) => {
123-
if (!imports[importPath][s]) {
124-
imports[importPath][s] = createImportedName(s, importPath);
125-
}
70+
return {
71+
OnceExit(root, postcss) {
72+
// Check the existing imports order and save refs
73+
root.walkRules((rule) => {
74+
const matches = icssImport.exec(rule.selector);
12675

127-
return imports[importPath][s];
128-
});
129-
}
76+
if (matches) {
77+
const [, /*match*/ doubleQuotePath, singleQuotePath] = matches;
78+
const importPath = doubleQuotePath || singleQuotePath;
79+
80+
addImportToGraph(importPath, "root", graph, visited);
13081

131-
decl.value = tmpSymbols.join(" ");
132-
}
133-
});
82+
existingImports[importPath] = rule;
83+
}
84+
});
13485

135-
const importsOrder = topologicalSort(graph, failOnWrongOrder);
86+
root.walkDecls(/^composes$/, (declaration) => {
87+
const matches = declaration.value.match(matchImports);
88+
89+
if (!matches) {
90+
return;
91+
}
92+
93+
let tmpSymbols;
94+
let [
95+
,
96+
/*match*/ symbols,
97+
doubleQuotePath,
98+
singleQuotePath,
99+
global,
100+
] = matches;
101+
102+
if (global) {
103+
// Composing globals simply means changing these classes to wrap them in global(name)
104+
tmpSymbols = symbols.split(/\s+/).map((s) => `global(${s})`);
105+
} else {
106+
const importPath = doubleQuotePath || singleQuotePath;
107+
108+
let parent = declaration.parent;
109+
let parentIndexes = "";
110+
111+
while (parent.type !== "root") {
112+
parentIndexes =
113+
parent.parent.index(parent) + "_" + parentIndexes;
114+
parent = parent.parent;
115+
}
136116

137-
if (importsOrder instanceof Error) {
138-
const importPath = importsOrder.nodes.find((importPath) =>
139-
// eslint-disable-next-line no-prototype-builtins
140-
importDecls.hasOwnProperty(importPath)
141-
);
142-
const decl = importDecls[importPath];
117+
const { selector } = declaration.parent;
118+
const parentRule = `_${parentIndexes}${selector}`;
143119

144-
const errMsg =
145-
"Failed to resolve order of composed modules " +
146-
serializeImports(importsOrder.nodes) +
147-
".";
120+
addImportToGraph(importPath, parentRule, graph, visited);
148121

149-
throw decl.error(errMsg, {
150-
plugin: "postcss-modules-extract-imports",
151-
word: "composes",
152-
});
153-
}
122+
importDecls[importPath] = declaration;
123+
imports[importPath] = imports[importPath] || {};
154124

155-
let lastImportRule;
125+
tmpSymbols = symbols.split(/\s+/).map((s) => {
126+
if (!imports[importPath][s]) {
127+
imports[importPath][s] = createImportedName(s, importPath);
128+
}
156129

157-
importsOrder.forEach((path) => {
158-
const importedSymbols = imports[path];
159-
let rule = existingImports[path];
130+
return imports[importPath][s];
131+
});
132+
}
160133

161-
if (!rule && importedSymbols) {
162-
rule = postcss.rule({
163-
selector: `:import("${path}")`,
164-
raws: { after: "\n" },
134+
declaration.value = tmpSymbols.join(" ");
165135
});
166136

167-
if (lastImportRule) {
168-
root.insertAfter(lastImportRule, rule);
169-
} else {
170-
root.prepend(rule);
137+
const importsOrder = topologicalSort(graph, failOnWrongOrder);
138+
139+
if (importsOrder instanceof Error) {
140+
const importPath = importsOrder.nodes.find((importPath) =>
141+
// eslint-disable-next-line no-prototype-builtins
142+
importDecls.hasOwnProperty(importPath)
143+
);
144+
const decl = importDecls[importPath];
145+
146+
throw decl.error(
147+
"Failed to resolve order of composed modules " +
148+
importsOrder.nodes
149+
.map((importPath) => "`" + importPath + "`")
150+
.join(", ") +
151+
".",
152+
{
153+
plugin: "postcss-modules-extract-imports",
154+
word: "composes",
155+
}
156+
);
171157
}
172-
}
173-
174-
lastImportRule = rule;
175-
176-
if (!importedSymbols) {
177-
return;
178-
}
179-
180-
Object.keys(importedSymbols).forEach((importedSymbol) => {
181-
rule.append(
182-
postcss.decl({
183-
value: importedSymbol,
184-
prop: importedSymbols[importedSymbol],
185-
raws: { before: "\n " },
186-
})
187-
);
188-
});
189-
});
158+
159+
let lastImportRule;
160+
161+
importsOrder.forEach((path) => {
162+
const importedSymbols = imports[path];
163+
let rule = existingImports[path];
164+
165+
if (!rule && importedSymbols) {
166+
rule = postcss.rule({
167+
selector: `:import("${path}")`,
168+
raws: { after: "\n" },
169+
});
170+
171+
if (lastImportRule) {
172+
root.insertAfter(lastImportRule, rule);
173+
} else {
174+
root.prepend(rule);
175+
}
176+
}
177+
178+
lastImportRule = rule;
179+
180+
if (!importedSymbols) {
181+
return;
182+
}
183+
184+
Object.keys(importedSymbols).forEach((importedSymbol) => {
185+
rule.append(
186+
postcss.decl({
187+
value: importedSymbol,
188+
prop: importedSymbols[importedSymbol],
189+
raws: { before: "\n " },
190+
})
191+
);
192+
});
193+
});
194+
},
195+
};
190196
},
191197
};
192198
};

src/topologicalSort.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ function walkGraph(node, graph, state, result, strict) {
3333
const length = children.length;
3434

3535
for (let i = 0; i < length; ++i) {
36-
const er = walkGraph(children[i], graph, state, result, strict);
36+
const error = walkGraph(children[i], graph, state, result, strict);
3737

38-
if (er instanceof Error) {
39-
return er;
38+
if (error instanceof Error) {
39+
return error;
4040
}
4141
}
4242

0 commit comments

Comments
 (0)