Skip to content

Commit bd8f968

Browse files
committed
add pure ignore comment for css modules
1 parent f1c05a5 commit bd8f968

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

src/index.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const selectorParser = require("postcss-selector-parser");
44
const valueParser = require("postcss-value-parser");
55
const { extractICSS } = require("icss-utils");
66

7+
const IGNORE_MARKER = "cssmodules-pure-ignore";
8+
79
const isSpacing = (node) => node.type === "combinator" && node.value === " ";
810

911
function normalizeNodeArray(nodes) {
@@ -26,6 +28,8 @@ function normalizeNodeArray(nodes) {
2628
}
2729

2830
function localizeNode(rule, mode, localAliasMap) {
31+
const isIgnored = hasIgnoreComment(rule);
32+
2933
const transform = (node, context) => {
3034
if (context.ignoreNextSpacing && !isSpacing(node)) {
3135
throw new Error("Missing whitespace after " + context.ignoreNextSpacing);
@@ -212,6 +216,10 @@ function localizeNode(rule, mode, localAliasMap) {
212216
break;
213217
}
214218

219+
if (isIgnored) {
220+
break;
221+
}
222+
215223
const isImportedValue = localAliasMap.has(node.value);
216224
const isImportedWithExplicitScope = isImportedValue && context.explicit;
217225

@@ -348,6 +356,10 @@ function localizeDeclarationValues(localize, declaration, context) {
348356
}
349357

350358
function localizeDeclaration(declaration, context) {
359+
if (hasIgnoreComment(declaration)) {
360+
return;
361+
}
362+
351363
const isAnimation = /animation$/i.test(declaration.prop);
352364

353365
if (isAnimation) {
@@ -471,6 +483,22 @@ function localizeDeclaration(declaration, context) {
471483
}
472484
}
473485

486+
function hasIgnoreComment(node) {
487+
if (!node.parent) {
488+
return false;
489+
}
490+
const indexInParent = node.parent.index(node);
491+
for (let i = indexInParent - 1; i >= 0; i--) {
492+
const prevNode = node.parent.nodes[i];
493+
if (prevNode.type === "comment") {
494+
return prevNode.text.trimStart().startsWith(IGNORE_MARKER)
495+
} else {
496+
break;
497+
}
498+
}
499+
return false;
500+
}
501+
474502
module.exports = (options = {}) => {
475503
if (
476504
options &&
@@ -554,7 +582,11 @@ module.exports = (options = {}) => {
554582
context.options = options;
555583
context.localAliasMap = localAliasMap;
556584

557-
if (pureMode && context.hasPureGlobals) {
585+
if (
586+
pureMode &&
587+
context.hasPureGlobals &&
588+
!hasIgnoreComment(selector)
589+
) {
558590
throw atRule.error(
559591
'Selector in at-rule"' +
560592
selector +
@@ -605,7 +637,7 @@ module.exports = (options = {}) => {
605637
context.options = options;
606638
context.localAliasMap = localAliasMap;
607639

608-
if (pureMode && context.hasPureGlobals) {
640+
if (pureMode && context.hasPureGlobals && !hasIgnoreComment(rule)) {
609641
throw rule.error(
610642
'Selector "' +
611643
rule.selector +

test/index.test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,68 @@ const tests = [
10151015
options: { mode: "pure" },
10161016
expected: ":export { foo: __foo; }",
10171017
},
1018+
{
1019+
name: "global selectors after an ignore comments should be pure",
1020+
options: { mode: "pure" },
1021+
input: `/* cssmodules-pure-ignore */
1022+
.global { a_value: some-value; }`,
1023+
expected: `/* cssmodules-pure-ignore */
1024+
.global { a_value: some-value; }`,
1025+
},
1026+
{
1027+
name: "global selectors after an ignore comments with postfix stays pure",
1028+
options: { mode: "pure" },
1029+
input: `/* cssmodules-pure-ignore With additional explanation */
1030+
.global { a_value: some-value; }`,
1031+
expected: `/* cssmodules-pure-ignore With additional explanation */
1032+
.global { a_value: some-value; }`,
1033+
},
1034+
{
1035+
name: "global selector after an ignore comments should still localize its properties",
1036+
options: { mode: "pure" },
1037+
input: `/* cssmodules-pure-ignore */
1038+
.global {
1039+
animation: fadeOut;
1040+
}`,
1041+
expected: `/* cssmodules-pure-ignore */
1042+
.global {
1043+
animation: :local(fadeOut);
1044+
}`,
1045+
},
1046+
{
1047+
name: "global selector after an ignore comments should still localize its child selectors",
1048+
options: { mode: "pure" },
1049+
input: `/* cssmodules-pure-ignore */
1050+
.outer {
1051+
.inner { a_value: some-value; }
1052+
}`,
1053+
expected: `/* cssmodules-pure-ignore */
1054+
.outer {
1055+
:local(.inner) { a_value: some-value; }
1056+
}`,
1057+
},
1058+
{
1059+
name: "global animation after an ignore comments should be pure",
1060+
options: { mode: "pure" },
1061+
input: `.foo { /* cssmodules-pure-ignore */
1062+
animation: fadeOut; }`,
1063+
expected: `:local(.foo) { /* cssmodules-pure-ignore */
1064+
animation: fadeOut; }`,
1065+
},
1066+
{
1067+
name: "global follow up properties after an ignore comments should be localized",
1068+
options: { mode: "pure" },
1069+
input: `.foo {
1070+
/* cssmodules-pure-ignore */
1071+
animation: fadeOut;
1072+
&:disabled { animation-name: localAnimation; }
1073+
}`,
1074+
expected: `:local(.foo) {
1075+
/* cssmodules-pure-ignore */
1076+
animation: fadeOut;
1077+
&:disabled { animation-name: :local(localAnimation); }
1078+
}`,
1079+
},
10181080
{
10191081
name: "handle negative animation-delay in animation shorthand",
10201082
input: ".foo { animation: 1s -500ms; }",

0 commit comments

Comments
 (0)