Skip to content

Commit 23651dd

Browse files
Merge remote-tracking branch 'origin/master'
2 parents dc58f6e + ff2721e commit 23651dd

File tree

3 files changed

+445
-424
lines changed

3 files changed

+445
-424
lines changed

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"url": "https://github.com/css-modules/postcss-modules-local-by-default.git"
1414
},
1515
"engines": {
16-
"node": ">= 10.13.0 || >= 12.13.0 || >= 14"
16+
"node": "^10 || ^12 || >= 14"
1717
},
1818
"keywords": [
1919
"css-modules",
@@ -39,14 +39,14 @@
3939
},
4040
"devDependencies": {
4141
"coveralls": "^3.1.0",
42-
"eslint": "^7.9.0",
42+
"eslint": "^7.10.0",
4343
"husky": "^4.3.0",
44-
"jest": "^26.4.2",
44+
"jest": "^26.5.2",
4545
"lint-staged": "^10.4.0",
46-
"postcss": "^8.0.7",
46+
"postcss": "^8.1.0",
4747
"prettier": "^2.1.2"
4848
},
4949
"peerDependencies": {
50-
"postcss": "^8.0.0"
50+
"postcss": "^8.1.0"
5151
}
5252
}

src/index.js

+89-76
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,6 @@ const { extractICSS } = require("icss-utils");
66

77
const isSpacing = (node) => node.type === "combinator" && node.value === " ";
88

9-
function getImportLocalAliases(icssImports) {
10-
const localAliases = new Map();
11-
12-
Object.keys(icssImports).forEach((key) => {
13-
Object.keys(icssImports[key]).forEach((prop) => {
14-
localAliases.set(prop, icssImports[key][prop]);
15-
});
16-
});
17-
18-
return localAliases;
19-
}
20-
219
function normalizeNodeArray(nodes) {
2210
const array = [];
2311

@@ -432,6 +420,8 @@ function localizeDecl(decl, context) {
432420
}
433421
}
434422

423+
const isVisited = Symbol("isVisited");
424+
435425
module.exports = (options = {}) => {
436426
if (options && options.mode) {
437427
if (
@@ -450,85 +440,108 @@ module.exports = (options = {}) => {
450440

451441
return {
452442
postcssPlugin: "postcss-modules-local-by-default",
453-
RootExit(root) {
454-
const { icssImports } = extractICSS(root, false);
455-
const localAliasMap = getImportLocalAliases(icssImports);
443+
prepare() {
444+
const localAliasMap = new Map();
456445

457-
root.walkAtRules(function (atrule) {
458-
if (/keyframes$/i.test(atrule.name)) {
459-
const globalMatch = /^\s*:global\s*\((.+)\)\s*$/.exec(atrule.params);
460-
const localMatch = /^\s*:local\s*\((.+)\)\s*$/.exec(atrule.params);
446+
return {
447+
Once(root) {
448+
const { icssImports } = extractICSS(root, false);
461449

462-
let globalKeyframes = globalMode;
450+
Object.keys(icssImports).forEach((key) => {
451+
Object.keys(icssImports[key]).forEach((prop) => {
452+
localAliasMap.set(prop, icssImports[key][prop]);
453+
});
454+
});
455+
},
456+
AtRule(atRule) {
457+
if (atRule[isVisited]) {
458+
return;
459+
}
463460

464-
if (globalMatch) {
465-
if (pureMode) {
466-
throw atrule.error(
467-
"@keyframes :global(...) is not allowed in pure mode"
468-
);
469-
}
470-
atrule.params = globalMatch[1];
471-
globalKeyframes = true;
472-
} else if (localMatch) {
473-
atrule.params = localMatch[0];
474-
globalKeyframes = false;
475-
} else if (!globalMode) {
476-
if (atrule.params && !localAliasMap.has(atrule.params)) {
477-
atrule.params = ":local(" + atrule.params + ")";
461+
if (/keyframes$/i.test(atRule.name)) {
462+
const globalMatch = /^\s*:global\s*\((.+)\)\s*$/.exec(
463+
atRule.params
464+
);
465+
const localMatch = /^\s*:local\s*\((.+)\)\s*$/.exec(atRule.params);
466+
467+
let globalKeyframes = globalMode;
468+
469+
if (globalMatch) {
470+
if (pureMode) {
471+
throw atRule.error(
472+
"@keyframes :global(...) is not allowed in pure mode"
473+
);
474+
}
475+
atRule.params = globalMatch[1];
476+
globalKeyframes = true;
477+
} else if (localMatch) {
478+
atRule.params = localMatch[0];
479+
globalKeyframes = false;
480+
} else if (!globalMode) {
481+
if (atRule.params && !localAliasMap.has(atRule.params)) {
482+
atRule.params = ":local(" + atRule.params + ")";
483+
}
478484
}
479-
}
480485

481-
atrule.walkDecls(function (decl) {
482-
localizeDecl(decl, {
483-
localAliasMap,
484-
options: options,
485-
global: globalKeyframes,
486-
});
487-
});
488-
} else if (atrule.nodes) {
489-
atrule.nodes.forEach(function (decl) {
490-
if (decl.type === "decl") {
486+
atRule.walkDecls(function (decl) {
491487
localizeDecl(decl, {
492488
localAliasMap,
493489
options: options,
494-
global: globalMode,
490+
global: globalKeyframes,
495491
});
496-
}
497-
});
498-
}
499-
});
492+
});
493+
} else if (atRule.nodes) {
494+
atRule.nodes.forEach(function (decl) {
495+
if (decl.type === "decl") {
496+
localizeDecl(decl, {
497+
localAliasMap,
498+
options: options,
499+
global: globalMode,
500+
});
501+
}
502+
});
503+
}
500504

501-
root.walkRules(function (rule) {
502-
if (
503-
rule.parent &&
504-
rule.parent.type === "atrule" &&
505-
/keyframes$/i.test(rule.parent.name)
506-
) {
507-
// ignore keyframe rules
508-
return;
509-
}
505+
atRule[isVisited] = true;
506+
},
507+
Rule(rule) {
508+
if (rule[isVisited]) {
509+
return;
510+
}
510511

511-
const context = localizeNode(rule, options.mode, localAliasMap);
512+
if (
513+
rule.parent &&
514+
rule.parent.type === "atrule" &&
515+
/keyframes$/i.test(rule.parent.name)
516+
) {
517+
// ignore keyframe rules
518+
return;
519+
}
512520

513-
context.options = options;
514-
context.localAliasMap = localAliasMap;
521+
const context = localizeNode(rule, options.mode, localAliasMap);
515522

516-
if (pureMode && context.hasPureGlobals) {
517-
throw rule.error(
518-
'Selector "' +
519-
rule.selector +
520-
'" is not pure ' +
521-
"(pure selectors must contain at least one local class or id)"
522-
);
523-
}
523+
context.options = options;
524+
context.localAliasMap = localAliasMap;
525+
526+
if (pureMode && context.hasPureGlobals) {
527+
throw rule.error(
528+
'Selector "' +
529+
rule.selector +
530+
'" is not pure ' +
531+
"(pure selectors must contain at least one local class or id)"
532+
);
533+
}
524534

525-
rule.selector = context.selector;
535+
rule.selector = context.selector;
526536

527-
// Less-syntax mixins parse as rules with no nodes
528-
if (rule.nodes) {
529-
rule.nodes.forEach((decl) => localizeDecl(decl, context));
530-
}
531-
});
537+
// Less-syntax mixins parse as rules with no nodes
538+
if (rule.nodes) {
539+
rule.nodes.forEach((decl) => localizeDecl(decl, context));
540+
}
541+
542+
rule[isVisited] = true;
543+
},
544+
};
532545
},
533546
};
534547
};

0 commit comments

Comments
 (0)