Skip to content

Commit 6eb06cf

Browse files
committed
ignore pure errors
1 parent f1c05a5 commit 6eb06cf

File tree

2 files changed

+167
-3
lines changed

2 files changed

+167
-3
lines changed

src/index.js

+26-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,26 @@ 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

11+
function hasIgnoreComment(node) {
12+
if (!node.parent) {
13+
return false;
14+
}
15+
const indexInParent = node.parent.index(node);
16+
for (let i = indexInParent - 1; i >= 0; i--) {
17+
const prevNode = node.parent.nodes[i];
18+
if (prevNode.type === "comment") {
19+
return prevNode.text.trimStart().startsWith(IGNORE_MARKER);
20+
} else {
21+
break;
22+
}
23+
}
24+
return false;
25+
}
26+
927
function normalizeNodeArray(nodes) {
1028
const array = [];
1129

@@ -26,6 +44,7 @@ function normalizeNodeArray(nodes) {
2644
}
2745

2846
function localizeNode(rule, mode, localAliasMap) {
47+
const isIgnored = hasIgnoreComment(rule);
2948
const transform = (node, context) => {
3049
if (context.ignoreNextSpacing && !isSpacing(node)) {
3150
throw new Error("Missing whitespace after " + context.ignoreNextSpacing);
@@ -514,7 +533,7 @@ module.exports = (options = {}) => {
514533
let globalKeyframes = globalMode;
515534

516535
if (globalMatch) {
517-
if (pureMode) {
536+
if (pureMode && !hasIgnoreComment(atRule)) {
518537
throw atRule.error(
519538
"@keyframes :global(...) is not allowed in pure mode"
520539
);
@@ -554,7 +573,11 @@ module.exports = (options = {}) => {
554573
context.options = options;
555574
context.localAliasMap = localAliasMap;
556575

557-
if (pureMode && context.hasPureGlobals) {
576+
if (
577+
pureMode &&
578+
context.hasPureGlobals &&
579+
!hasIgnoreComment(atRule)
580+
) {
558581
throw atRule.error(
559582
'Selector in at-rule"' +
560583
selector +
@@ -605,7 +628,7 @@ module.exports = (options = {}) => {
605628
context.options = options;
606629
context.localAliasMap = localAliasMap;
607630

608-
if (pureMode && context.hasPureGlobals) {
631+
if (pureMode && context.hasPureGlobals && !hasIgnoreComment(rule)) {
609632
throw rule.error(
610633
'Selector "' +
611634
rule.selector +

test/index.test.js

+141
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,147 @@ const tests = [
876876
options: { mode: "pure" },
877877
error: /is not pure/,
878878
},
879+
{
880+
name: "should suppress errors for global selectors after ignore comment",
881+
options: { mode: "pure" },
882+
input: `/* cssmodules-pure-ignore */
883+
:global(.foo) { color: blue; }`,
884+
expected: `/* cssmodules-pure-ignore */
885+
.foo { color: blue; }`,
886+
},
887+
{
888+
name: "should allow additional text in ignore comment",
889+
options: { mode: "pure" },
890+
input: `/* cssmodules-pure-ignore - needed for third party integration */
891+
:global(#foo) { color: blue; }`,
892+
expected: `/* cssmodules-pure-ignore - needed for third party integration */
893+
#foo { color: blue; }`,
894+
},
895+
{
896+
name: "should not affect rules after the ignored block",
897+
options: { mode: "pure" },
898+
input: `/* cssmodules-pure-ignore */
899+
:global(.foo) { color: blue; }
900+
:global(.bar) { color: red; }`,
901+
error: /is not pure/,
902+
},
903+
{
904+
name: "should work with nested global selectors in ignored block",
905+
options: { mode: "pure" },
906+
input: `/* cssmodules-pure-ignore */
907+
:global(.foo) {
908+
:global(.bar) { color: blue; }
909+
}`,
910+
error: /is not pure/,
911+
},
912+
{
913+
name: "should work with ignored nested global selectors in ignored block",
914+
options: { mode: "pure" },
915+
input: `/* cssmodules-pure-ignore */
916+
:global(.foo) {
917+
/* cssmodules-pure-ignore */
918+
:global(.bar) { color: blue; }
919+
}`,
920+
expected: `/* cssmodules-pure-ignore */
921+
.foo {
922+
/* cssmodules-pure-ignore */
923+
.bar { color: blue; }
924+
}`,
925+
},
926+
{
927+
name: "should work with view transitions in ignored block",
928+
options: { mode: "pure" },
929+
input: `/* cssmodules-pure-ignore */
930+
::view-transition-group(modal) {
931+
animation-duration: 300ms;
932+
}`,
933+
expected: `/* cssmodules-pure-ignore */
934+
::view-transition-group(modal) {
935+
animation-duration: 300ms;
936+
}`,
937+
},
938+
{
939+
name: "should work with keyframes in ignored block",
940+
options: { mode: "pure" },
941+
input: `/* cssmodules-pure-ignore */
942+
@keyframes :global(fadeOut) {
943+
from { opacity: 1; }
944+
to { opacity: 0; }
945+
}`,
946+
expected: `/* cssmodules-pure-ignore */
947+
@keyframes fadeOut {
948+
from { opacity: 1; }
949+
to { opacity: 0; }
950+
}`,
951+
},
952+
{
953+
name: "should work in media queries",
954+
options: { mode: "pure" },
955+
input: `@media (min-width: 768px) {
956+
/* cssmodules-pure-ignore */
957+
:global(.foo) { color: blue; }
958+
}`,
959+
expected: `@media (min-width: 768px) {
960+
/* cssmodules-pure-ignore */
961+
.foo { color: blue; }
962+
}`,
963+
},
964+
{
965+
name: "should handle multiple ignore comments",
966+
options: { mode: "pure" },
967+
input: `/* cssmodules-pure-ignore */
968+
:global(.foo) { color: blue; }
969+
.local { color: green; }
970+
/* cssmodules-pure-ignore */
971+
:global(.bar) { color: red; }`,
972+
expected: `/* cssmodules-pure-ignore */
973+
.foo { color: blue; }
974+
:local(.local) { color: green; }
975+
/* cssmodules-pure-ignore */
976+
.bar { color: red; }`,
977+
},
978+
{
979+
name: "should work with complex selectors in ignored block",
980+
options: { mode: "pure" },
981+
input: `/* cssmodules-pure-ignore */
982+
:global(.foo):hover > :global(.bar) + :global(.baz) {
983+
color: blue;
984+
}`,
985+
expected: `/* cssmodules-pure-ignore */
986+
.foo:hover > .bar + .baz {
987+
color: blue;
988+
}`,
989+
},
990+
{
991+
name: "should work with multiple selectors in ignored block",
992+
options: { mode: "pure" },
993+
input: `/* cssmodules-pure-ignore */
994+
:global(.foo),
995+
:global(.bar),
996+
:global(.baz) {
997+
color: blue;
998+
}`,
999+
expected: `/* cssmodules-pure-ignore */
1000+
.foo,
1001+
.bar,
1002+
.baz {
1003+
color: blue;
1004+
}`,
1005+
},
1006+
{
1007+
name: "should work with pseudo-elements in ignored block",
1008+
options: { mode: "pure" },
1009+
input: `/* cssmodules-pure-ignore */
1010+
:global(.foo)::before,
1011+
:global(.foo)::after {
1012+
content: '';
1013+
}`,
1014+
expected: `/* cssmodules-pure-ignore */
1015+
.foo::before,
1016+
.foo::after {
1017+
content: '';
1018+
}`,
1019+
},
8791020
{
8801021
name: "css nesting",
8811022
input: `

0 commit comments

Comments
 (0)