Skip to content

Commit 2818799

Browse files
committed
Generate scoped names instead of :local wrappers
1 parent 963e95f commit 2818799

File tree

4 files changed

+432
-120
lines changed

4 files changed

+432
-120
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
},
5656
"dependencies": {
5757
"css-selector-tokenizer": "^0.7.0",
58+
"generic-names": "^1.0.2",
59+
"icss-utils": "^2.1.0",
5860
"postcss": "^6.0.1"
5961
},
6062
"devDependencies": {

src/index.js

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* eslint-env node */
22
import postcss from "postcss";
33
import Tokenizer from "css-selector-tokenizer";
4+
import { extractICSS, createICSSRules } from "icss-utils";
5+
import genericNames from "generic-names";
46

57
const plugin = "postcss-modules-local-by-default";
68

@@ -19,7 +21,7 @@ const isModifier = node =>
1921
node.type === "pseudo-class" &&
2022
(node.name === "local" || node.name === "global");
2123

22-
function localizeNode(node, { mode, inside }) {
24+
function localizeNode(node, { mode, inside, getAlias }) {
2325
const newNodes = node.nodes.reduce((acc, n, index, nodes) => {
2426
switch (n.type) {
2527
case "spacing":
@@ -62,28 +64,25 @@ function localizeNode(node, { mode, inside }) {
6264
}
6365
return [
6466
...acc,
65-
...localizeNode(n.nodes[0], { mode: n.name, inside: n.name }).nodes
67+
...localizeNode(n.nodes[0], {
68+
mode: n.name,
69+
inside: n.name,
70+
getAlias
71+
}).nodes
6672
];
6773
} else {
6874
return [
6975
...acc,
7076
Object.assign({}, n, {
71-
nodes: localizeNode(n.nodes[0], { mode, inside }).nodes
77+
nodes: localizeNode(n.nodes[0], { mode, inside, getAlias }).nodes
7278
})
7379
];
7480
}
7581

7682
case "id":
7783
case "class":
7884
if (mode === "local") {
79-
return [
80-
...acc,
81-
{
82-
type: "nested-pseudo-class",
83-
name: "local",
84-
nodes: [n]
85-
}
86-
];
85+
return [...acc, Object.assign({}, n, { name: getAlias(n.name) })];
8786
}
8887
return [...acc, n];
8988

@@ -95,11 +94,11 @@ function localizeNode(node, { mode, inside }) {
9594
return Object.assign({}, node, { nodes: trimNodes(newNodes) });
9695
}
9796

98-
const localizeSelectors = (selectors, mode) => {
97+
const localizeSelectors = (selectors, mode, getAlias) => {
9998
const node = Tokenizer.parse(selectors);
10099
return Tokenizer.stringify(
101100
Object.assign({}, node, {
102-
nodes: node.nodes.map(n => localizeNode(n, { mode }))
101+
nodes: node.nodes.map(n => localizeNode(n, { mode, getAlias }))
103102
})
104103
);
105104
};
@@ -113,14 +112,29 @@ const walkRules = (css, callback) => {
113112
};
114113

115114
module.exports = postcss.plugin(plugin, (options = {}) => css => {
115+
const generateScopedName =
116+
options.generateScopedName ||
117+
genericNames("[name]__[local]---[hash:base64:5]");
118+
const input = (css && css.source && css.source.input) || {};
119+
const { icssImports, icssExports } = extractICSS(css);
120+
const aliases = {};
121+
const getAlias = name => {
122+
const alias = generateScopedName(name, input.from, input.css);
123+
aliases[name] = alias;
124+
return alias;
125+
};
116126
walkRules(css, rule => {
117127
try {
118128
rule.selector = localizeSelectors(
119129
rule.selector,
120-
options.mode === "global" ? "global" : "local"
130+
options.mode === "global" ? "global" : "local",
131+
getAlias
121132
);
122133
} catch (e) {
123134
throw rule.error(e.message);
124135
}
125136
});
137+
css.prepend(
138+
createICSSRules(icssImports, Object.assign({}, icssExports, aliases))
139+
);
126140
});

0 commit comments

Comments
 (0)