Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dec5b56

Browse files
committed
feat: add option to omit locals with empty declaration blocks
fixes css-modules/css-modules#127, fixes css-modules/css-modules#269
1 parent af015f1 commit dec5b56

File tree

4 files changed

+75
-13
lines changed

4 files changed

+75
-13
lines changed

‎src/index.js‎

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,19 @@ const plugin = (options = {}) => {
8585
const generateExportEntry =
8686
(options && options.generateExportEntry) || plugin.generateExportEntry;
8787
const exportGlobals = options && options.exportGlobals;
88+
const exportEmptyLocals =
89+
!options ||
90+
(typeof options.exportEmptyLocals === "undefined" ||
91+
options.exportEmptyLocals === null
92+
? true
93+
: options.exportEmptyLocals);
8894

8995
return {
9096
postcssPlugin: "postcss-modules-scope",
9197
Once(root, { rule }) {
9298
const exports = Object.create(null);
9399

94-
function exportScopedName(name, rawName) {
100+
function exportScopedName(name, rawName,includeSelfReference) {
95101
const scopedName = generateScopedName(
96102
rawName ? rawName : name,
97103
root.source.input.from,
@@ -107,30 +113,32 @@ const plugin = (options = {}) => {
107113

108114
exports[key] = exports[key] || [];
109115

110-
if (exports[key].indexOf(value) < 0) {
116+
if (includeSelfReference&&exports[key].indexOf(value) < 0) {
111117
exports[key].push(value);
112118
}
113119

114120
return scopedName;
115121
}
116122

117-
function localizeNode(node) {
123+
function localizeNode(node,exportSelfReference) {
118124
switch (node.type) {
119125
case "selector":
120-
node.nodes = node.map(localizeNode);
126+
node.nodes = node.map((n)=>localizeNode(n,exportSelfReference));
121127
return node;
122128
case "class":
123129
return selectorParser.className({
124130
value: exportScopedName(
125131
node.value,
126-
node.raws && node.raws.value ? node.raws.value : null
132+
node.raws && node.raws.value ? node.raws.value : null,
133+
exportSelfReference
127134
),
128135
});
129136
case "id": {
130137
return selectorParser.id({
131138
value: exportScopedName(
132139
node.value,
133-
node.raws && node.raws.value ? node.raws.value : null
140+
node.raws && node.raws.value ? node.raws.value : null,
141+
exportSelfReference
134142
),
135143
});
136144
}
@@ -141,15 +149,15 @@ const plugin = (options = {}) => {
141149
);
142150
}
143151

144-
function traverseNode(node) {
152+
function traverseNode(node,exportSelfReference) {
145153
switch (node.type) {
146154
case "pseudo":
147155
if (node.value === ":local") {
148156
if (node.nodes.length !== 1) {
149157
throw new Error('Unexpected comma (",") in :local block');
150158
}
151159

152-
const selector = localizeNode(node.first);
160+
const selector = localizeNode(node.first,exportSelfReference);
153161
// move the spaces that were around the psuedo selector to the first
154162
// non-container node
155163
selector.first.spaces = node.spaces;
@@ -172,7 +180,7 @@ const plugin = (options = {}) => {
172180
/* falls through */
173181
case "root":
174182
case "selector": {
175-
node.each(traverseNode);
183+
node.each((n)=>traverseNode(n,exportSelfReference));
176184
break;
177185
}
178186
case "id":
@@ -197,8 +205,14 @@ const plugin = (options = {}) => {
197205
// Find any :local selectors
198206
root.walkRules((rule) => {
199207
let parsedSelector = selectorParser().astSync(rule);
208+
const containsOwnDeclarations = rule.nodes.some(
209+
(node) => node.prop !== "composes" && node.prop !== "compose-with"
210+
);
200211

201-
rule.selector = traverseNode(parsedSelector.clone()).toString();
212+
rule.selector = traverseNode(
213+
parsedSelector.clone(),
214+
exportEmptyLocals || containsOwnDeclarations
215+
).toString();
202216

203217
rule.walkDecls(/composes|compose-with/i, (decl) => {
204218
const localNames = getSingleLocalNamesForComposes(parsedSelector);
@@ -249,7 +263,7 @@ const plugin = (options = {}) => {
249263
const input = localMatch.input;
250264
const matchPattern = localMatch[0];
251265
const matchVal = localMatch[1];
252-
const newVal = exportScopedName(matchVal);
266+
const newVal = exportScopedName(matchVal,undefined,true);
253267

254268
result = input.replace(matchPattern, newVal);
255269
} else {
@@ -274,11 +288,13 @@ const plugin = (options = {}) => {
274288
return;
275289
}
276290

277-
atRule.params = exportScopedName(localMatch[1]);
291+
atRule.params = exportScopedName(localMatch[1],undefined,true);
278292
});
279293

280294
// If we found any :locals, insert an :export rule
281-
const exportedNames = Object.keys(exports);
295+
const exportedNames = Object.keys(exports).filter(
296+
(exportedName) => exports[exportedName].length !== 0
297+
);
282298

283299
if (exportedNames.length > 0) {
284300
const exportRule = rule({ selector: ":export" });
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
._input__layer1A {
2+
color: red;
3+
}
4+
5+
._input__layer2A {
6+
}
7+
8+
._input__layer1B {
9+
}
10+
11+
._input__layer2B {
12+
background: blue;
13+
}
14+
15+
._input__layer3 {
16+
}
17+
18+
:export {
19+
layer1A: _input__layer1A;
20+
layer2A: _input__layer1A;
21+
layer2B: _input__layer2B;
22+
layer3: _input__layer1A _input__layer2B;
23+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
exportEmptyLocals: false,
3+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
:local(.layer1A) {
2+
color: red;
3+
}
4+
5+
:local(.layer2A) {
6+
composes: layer1A;
7+
}
8+
9+
:local(.layer1B) {
10+
}
11+
12+
:local(.layer2B) {
13+
background: blue;
14+
composes: layer1B;
15+
}
16+
17+
:local(.layer3) {
18+
composes: layer2A;
19+
composes: layer2B;
20+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /