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 3085be7

Browse files
feat: support @scope at-rule (#70)
1 parent 82628c2 commit 3085be7

File tree

2 files changed

+279
-4
lines changed

2 files changed

+279
-4
lines changed

‎src/index.js

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,12 @@ module.exports = (options = {}) => {
524524
} else if (localMatch) {
525525
atRule.params = localMatch[0];
526526
globalKeyframes = false;
527-
} else if (!globalMode) {
528-
if (atRule.params && !localAliasMap.has(atRule.params)) {
529-
atRule.params = ":local(" + atRule.params + ")";
530-
}
527+
} else if (
528+
atRule.params &&
529+
!globalMode &&
530+
!localAliasMap.has(atRule.params)
531+
) {
532+
atRule.params = ":local(" + atRule.params + ")";
531533
}
532534

533535
atRule.walkDecls((declaration) => {
@@ -537,6 +539,42 @@ module.exports = (options = {}) => {
537539
global: globalKeyframes,
538540
});
539541
});
542+
} else if (/scope$/i.test(atRule.name)) {
543+
atRule.params = atRule.params
544+
.split("to")
545+
.map((item) => {
546+
const selector = item.trim().slice(1, -1).trim();
547+
const context = localizeNode(
548+
selector,
549+
options.mode,
550+
localAliasMap
551+
);
552+
553+
context.options = options;
554+
context.localAliasMap = localAliasMap;
555+
556+
if (pureMode && context.hasPureGlobals) {
557+
throw atRule.error(
558+
'Selector in at-rule"' +
559+
selector +
560+
'" is not pure ' +
561+
"(pure selectors must contain at least one local class or id)"
562+
);
563+
}
564+
565+
return `(${context.selector})`;
566+
})
567+
.join(" to ");
568+
569+
atRule.nodes.forEach((declaration) => {
570+
if (declaration.type === "decl") {
571+
localizeDeclaration(declaration, {
572+
localAliasMap,
573+
options: options,
574+
global: globalMode,
575+
});
576+
}
577+
});
540578
} else if (atRule.nodes) {
541579
atRule.nodes.forEach((declaration) => {
542580
if (declaration.type === "decl") {

‎test/index.test.js

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,243 @@ const tests = [
10221022
input: ".foo { animation: 1s -500.0ms -a_value; }",
10231023
expected: ":local(.foo) { animation: 1s -500.0ms :local(-a_value); }",
10241024
},
1025+
{
1026+
name: "@scope at-rule",
1027+
input: `
1028+
.article-header {
1029+
color: red;
1030+
}
1031+
1032+
.article-body {
1033+
color: blue;
1034+
}
1035+
1036+
@scope (.article-body) to (.article-header) {
1037+
.article-body {
1038+
border: 5px solid black;
1039+
background-color: goldenrod;
1040+
}
1041+
}
1042+
1043+
@scope(.article-body)to(.article-header){
1044+
.article-footer {
1045+
border: 5px solid black;
1046+
}
1047+
}
1048+
1049+
@scope ( .article-body ) {
1050+
img {
1051+
border: 5px solid black;
1052+
background-color: goldenrod;
1053+
}
1054+
}
1055+
`,
1056+
expected: `
1057+
:local(.article-header) {
1058+
color: red;
1059+
}
1060+
1061+
:local(.article-body) {
1062+
color: blue;
1063+
}
1064+
1065+
@scope (:local(.article-body)) to (:local(.article-header)) {
1066+
:local(.article-body) {
1067+
border: 5px solid black;
1068+
background-color: goldenrod;
1069+
}
1070+
}
1071+
1072+
@scope(:local(.article-body)) to (:local(.article-header)){
1073+
:local(.article-footer) {
1074+
border: 5px solid black;
1075+
}
1076+
}
1077+
1078+
@scope (:local(.article-body)) {
1079+
img {
1080+
border: 5px solid black;
1081+
background-color: goldenrod;
1082+
}
1083+
}
1084+
`,
1085+
},
1086+
{
1087+
name: "@scope at-rule #1",
1088+
input: `
1089+
@scope (.article-body) to (figure) {
1090+
.article-footer {
1091+
border: 5px solid black;
1092+
}
1093+
}
1094+
`,
1095+
expected: `
1096+
@scope (:local(.article-body)) to (figure) {
1097+
:local(.article-footer) {
1098+
border: 5px solid black;
1099+
}
1100+
}
1101+
`,
1102+
},
1103+
{
1104+
name: "@scope at-rule #2",
1105+
input: `
1106+
@scope (:local(.article-body)) to (:global(.class)) {
1107+
.article-footer {
1108+
border: 5px solid black;
1109+
}
1110+
:local(.class-1) {
1111+
color: red;
1112+
}
1113+
:global(.class-2) {
1114+
color: blue;
1115+
}
1116+
}
1117+
`,
1118+
expected: `
1119+
@scope (:local(.article-body)) to (.class) {
1120+
:local(.article-footer) {
1121+
border: 5px solid black;
1122+
}
1123+
:local(.class-1) {
1124+
color: red;
1125+
}
1126+
.class-2 {
1127+
color: blue;
1128+
}
1129+
}
1130+
`,
1131+
},
1132+
{
1133+
name: "@scope at-rule #3",
1134+
options: { mode: "global" },
1135+
input: `
1136+
@scope (:local(.article-header)) to (:global(.class)) {
1137+
.article-footer {
1138+
border: 5px solid black;
1139+
}
1140+
:local(.class-1) {
1141+
color: red;
1142+
}
1143+
:global(.class-2) {
1144+
color: blue;
1145+
}
1146+
}
1147+
`,
1148+
expected: `
1149+
@scope (:local(.article-header)) to (.class) {
1150+
.article-footer {
1151+
border: 5px solid black;
1152+
}
1153+
:local(.class-1) {
1154+
color: red;
1155+
}
1156+
.class-2 {
1157+
color: blue;
1158+
}
1159+
}
1160+
`,
1161+
},
1162+
{
1163+
name: "@scope at-rule #4",
1164+
options: { mode: "pure" },
1165+
input: `
1166+
@scope (.article-header) to (.class) {
1167+
.article-footer {
1168+
border: 5px solid black;
1169+
}
1170+
.class-1 {
1171+
color: red;
1172+
}
1173+
.class-2 {
1174+
color: blue;
1175+
}
1176+
}
1177+
`,
1178+
expected: `
1179+
@scope (:local(.article-header)) to (:local(.class)) {
1180+
:local(.article-footer) {
1181+
border: 5px solid black;
1182+
}
1183+
:local(.class-1) {
1184+
color: red;
1185+
}
1186+
:local(.class-2) {
1187+
color: blue;
1188+
}
1189+
}
1190+
`,
1191+
},
1192+
{
1193+
name: "@scope at-rule #5",
1194+
input: `
1195+
@scope (.article-header) to (.class) {
1196+
.article-footer {
1197+
src: url("./font.woff");
1198+
}
1199+
}
1200+
`,
1201+
options: {
1202+
rewriteUrl: function (global, url) {
1203+
const mode = global ? "global" : "local";
1204+
return "(" + mode + ")" + url + '"' + mode + '"';
1205+
},
1206+
},
1207+
expected: `
1208+
@scope (:local(.article-header)) to (:local(.class)) {
1209+
:local(.article-footer) {
1210+
src: url("(local)./font.woff\\"local\\"");
1211+
}
1212+
}
1213+
`,
1214+
},
1215+
{
1216+
name: "@scope at-rule #6",
1217+
input: `
1218+
.foo {
1219+
@scope (.article-header) to (.class) {
1220+
:scope {
1221+
background: blue;
1222+
}
1223+
1224+
.bar {
1225+
color: red;
1226+
}
1227+
}
1228+
}
1229+
`,
1230+
expected: `
1231+
:local(.foo) {
1232+
@scope (:local(.article-header)) to (:local(.class)) {
1233+
:scope {
1234+
background: blue;
1235+
}
1236+
1237+
:local(.bar) {
1238+
color: red;
1239+
}
1240+
}
1241+
}
1242+
`,
1243+
},
1244+
{
1245+
name: "@scope at-rule #7",
1246+
options: { mode: "pure" },
1247+
input: `
1248+
@scope (:global(.article-header).foo) to (:global(.class).bar) {
1249+
.bar {
1250+
color: red;
1251+
}
1252+
}
1253+
`,
1254+
expected: `
1255+
@scope (.article-header:local(.foo)) to (.class:local(.bar)) {
1256+
:local(.bar) {
1257+
color: red;
1258+
}
1259+
}
1260+
`,
1261+
},
10251262
];
10261263

10271264
function process(css, options) {

0 commit comments

Comments
(0)

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