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 ba7e8ef

Browse files
feat: added support a cssmodules-pure-no-check comment
1 parent 39a2f78 commit ba7e8ef

File tree

3 files changed

+161
-11
lines changed

3 files changed

+161
-11
lines changed

‎README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Declarations (mode `local`, by default):
5959
In pure mode, all selectors must contain at least one local class or id
6060
selector
6161

62-
To ignore this rule for a specific selector, add the following comment in front
62+
To ignore this rule for a specific selector, add the a `/* cssmodules-pure-ignore */` comment in front
6363
of the selector:
6464

6565
```css
@@ -69,6 +69,20 @@ of the selector:
6969
}
7070
```
7171

72+
or by adding a `/* cssmodules-pure-no-check */` comment at the top of a file to disable this check for the whole file:
73+
74+
```css
75+
/* cssmodules-pure-no-check */
76+
77+
:global(#modal-backdrop) {
78+
...;
79+
}
80+
81+
:global(#my-id) {
82+
...;
83+
}
84+
```
85+
7286
## Building
7387

7488
```bash

‎src/index.js

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,32 @@ 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";
7+
const IGNORE_FILE_MARKER = "cssmodules-pure-no-check";
8+
const IGNORE_NEXT_LINE_MARKER = "cssmodules-pure-ignore";
89

910
const isSpacing = (node) => node.type === "combinator" && node.value === " ";
1011

12+
const isPureCheckDisabled = (root) => {
13+
for (const node of root.nodes) {
14+
if (node.type !== "comment") {
15+
return false;
16+
}
17+
if (node.text.trim().startsWith(IGNORE_FILE_MARKER)) {
18+
return true;
19+
}
20+
}
21+
return false;
22+
};
23+
1124
function getIgnoreComment(node) {
1225
if (!node.parent) {
1326
return;
1427
}
15-
1628
const indexInParent = node.parent.index(node);
17-
1829
for (let i = indexInParent - 1; i >= 0; i--) {
1930
const prevNode = node.parent.nodes[i];
2031
if (prevNode.type === "comment") {
21-
if (prevNode.text.trimStart().startsWith(IGNORE_MARKER)) {
32+
if (prevNode.text.trimStart().startsWith(IGNORE_NEXT_LINE_MARKER)) {
2233
return prevNode;
2334
}
2435
} else {
@@ -552,6 +563,7 @@ module.exports = (options = {}) => {
552563
return {
553564
Once(root) {
554565
const { icssImports } = extractICSS(root, false);
566+
const enforcePureMode = pureMode && !isPureCheckDisabled(root);
555567

556568
Object.keys(icssImports).forEach((key) => {
557569
Object.keys(icssImports[key]).forEach((prop) => {
@@ -571,9 +583,8 @@ module.exports = (options = {}) => {
571583
let globalKeyframes = globalMode;
572584

573585
if (globalMatch) {
574-
if (pureMode) {
586+
if (enforcePureMode) {
575587
const ignoreComment = getIgnoreComment(atRule);
576-
577588
if (!ignoreComment) {
578589
throw atRule.error(
579590
"@keyframes :global(...) is not allowed in pure mode"
@@ -582,7 +593,6 @@ module.exports = (options = {}) => {
582593
ignoreComment.remove();
583594
}
584595
}
585-
586596
atRule.params = globalMatch[1];
587597
globalKeyframes = true;
588598
} else if (localMatch) {
@@ -626,7 +636,11 @@ module.exports = (options = {}) => {
626636
context.options = options;
627637
context.localAliasMap = localAliasMap;
628638

629-
if (pureMode && context.hasPureGlobals && !ignoreComment) {
639+
if (
640+
enforcePureMode &&
641+
context.hasPureGlobals &&
642+
!ignoreComment
643+
) {
630644
throw atRule.error(
631645
'Selector in at-rule"' +
632646
selector +
@@ -677,8 +691,10 @@ module.exports = (options = {}) => {
677691
context.options = options;
678692
context.localAliasMap = localAliasMap;
679693

680-
const ignoreComment = pureMode ? getIgnoreComment(rule) : undefined;
681-
const isNotPure = pureMode && !isPureSelector(context, rule);
694+
const ignoreComment = enforcePureMode
695+
? getIgnoreComment(rule)
696+
: undefined;
697+
const isNotPure = enforcePureMode && !isPureSelector(context, rule);
682698

683699
if (
684700
isNotPure &&

‎test/index.test.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,126 @@ const tests = [
11801180
content: '';
11811181
}`,
11821182
},
1183+
{
1184+
name: "should disable pure mode checks for entire file with no-check comment",
1185+
options: { mode: "pure" },
1186+
input: `/* cssmodules-pure-no-check */
1187+
:global(.foo) { border: 1px solid #e2e8f0 }
1188+
:global(.bar) { box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) }
1189+
:global(.baz) { background: #4299e1 }`,
1190+
expected: `/* cssmodules-pure-no-check */
1191+
.foo { border: 1px solid #e2e8f0 }
1192+
.bar { box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1) }
1193+
.baz { background: #4299e1 }`,
1194+
},
1195+
{
1196+
name: "should disable pure mode checks for nested selectors",
1197+
options: { mode: "pure" },
1198+
input: `/* cssmodules-pure-no-check */
1199+
:global(.foo) {
1200+
&:hover { border-color: #cbd5e0 }
1201+
& :global(.bar) { color: blue }
1202+
}`,
1203+
expected: `/* cssmodules-pure-no-check */
1204+
.foo {
1205+
&:hover { border-color: #cbd5e0 }
1206+
& .bar { color: blue }
1207+
}`,
1208+
},
1209+
{
1210+
name: "should ignore no-check comment if not at root level",
1211+
options: { mode: "pure" },
1212+
input: `:global(.bar) { color: blue }
1213+
/* cssmodules-pure-no-check */`,
1214+
error: /isnotpure/,
1215+
},
1216+
{
1217+
name: "should ignore no-check comment if not at root level #2",
1218+
options: { mode: "pure" },
1219+
input: `/* Some file description */
1220+
.class { color: red; }
1221+
/* cssmodules-pure-no-check */
1222+
:global(.foo) { color: blue }`,
1223+
error: /isnotpure/,
1224+
},
1225+
{
1226+
name: "should allow other comments before no-check comment",
1227+
options: { mode: "pure" },
1228+
input: `/* Some file description */
1229+
/* cssmodules-pure-no-check */
1230+
:global(.foo) { color: blue }`,
1231+
expected: `/* Some file description */
1232+
/* cssmodules-pure-no-check */
1233+
.foo { color: blue }`,
1234+
},
1235+
{
1236+
name: "should disable pure mode checks for deep nested selectors",
1237+
options: { mode: "pure" },
1238+
input: `/* cssmodules-pure-no-check */
1239+
:global(.foo) { max-width: 600px }
1240+
:global(.bar) { background: #fafafa }
1241+
:global(.baz) {
1242+
:global(.foobar) {
1243+
&::-webkit-scrollbar { width: 8px }
1244+
}
1245+
}`,
1246+
expected: `/* cssmodules-pure-no-check */
1247+
.foo { max-width: 600px }
1248+
.bar { background: #fafafa }
1249+
.baz {
1250+
.foobar {
1251+
&::-webkit-scrollbar { width: 8px }
1252+
}
1253+
}`,
1254+
},
1255+
{
1256+
name: "should work with keyframes when no-check is enabled",
1257+
options: { mode: "pure" },
1258+
input: `/* cssmodules-pure-no-check */
1259+
@keyframes :global(fadeIn) {
1260+
from { opacity: 0 }
1261+
to { opacity: 1 }
1262+
}
1263+
:global(.animate) { animation: global(fadeIn) 0.3s }`,
1264+
expected: `/* cssmodules-pure-no-check */
1265+
@keyframes fadeIn {
1266+
from { opacity: 0 }
1267+
to { opacity: 1 }
1268+
}
1269+
.animate { animation: fadeIn 0.3s }`,
1270+
},
1271+
{
1272+
name: "should allow multiline no-check comment",
1273+
options: { mode: "pure" },
1274+
input: `/*
1275+
cssmodules-pure-no-check
1276+
*/
1277+
:global(.foo) { color: blue }`,
1278+
expected: `/*
1279+
cssmodules-pure-no-check
1280+
*/
1281+
.foo { color: blue }`,
1282+
},
1283+
{
1284+
name: "should allow additional text in no-check comment",
1285+
options: { mode: "pure" },
1286+
input: `/* cssmodules-pure-no-check - needed for styling third-party components */
1287+
:global(.foo) { color: blue }`,
1288+
expected: `/* cssmodules-pure-no-check - needed for styling third-party components */
1289+
.foo { color: blue }`,
1290+
},
1291+
{
1292+
name: "should work with media queries when no-check is enabled",
1293+
options: { mode: "pure" },
1294+
input: `/* cssmodules-pure-no-check */
1295+
@media (max-width: 768px) {
1296+
:global(.foo) { position: fixed }
1297+
}`,
1298+
expected: `/* cssmodules-pure-no-check */
1299+
@media (max-width: 768px) {
1300+
.foo { position: fixed }
1301+
}`,
1302+
},
11831303
{
11841304
name: "css nesting",
11851305
input: `

0 commit comments

Comments
(0)

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