Skip to content

Commit

Permalink
Don't lowercase element names and attribute names in selectors
Browse files Browse the repository at this point in the history
https://www.w3.org/TR/css3-selectors/#casesens

> All Selectors syntax is case-insensitive within the ASCII range (i.e.
> [a-z] and [A-Z] are equivalent), except for parts that are not under the
> control of Selectors. The case sensitivity of document language element
> names, attribute names, and attribute values in selectors depends on the
> document language. For example, in HTML, element names are
> case-insensitive, but in XML, they are case-sensitive.

Fixes #3304.
  • Loading branch information
lydell committed Nov 25, 2017
1 parent b941e30 commit 9fb1a3d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 44 deletions.
9 changes: 2 additions & 7 deletions src/printer-postcss.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,7 @@ function genericPrint(path, options, print) {
return adjustStrings(n.value, options);
}
case "selector-tag": {
const parent = path.getParentNode();
const index = parent.nodes.indexOf(n);
const previous = index > 0 ? parent.nodes[index - 1] : null;
return previous && previous.type === "selector-nesting"
? n.value
: maybeToLowerCase(n.value);
return n.value;
}
case "selector-id": {
return concat(["#", n.value]);
Expand All @@ -238,7 +233,7 @@ function genericPrint(path, options, print) {
case "selector-attribute": {
return concat([
"[",
maybeToLowerCase(n.attribute),
n.attribute,
n.operator ? n.operator : "",
n.value
? quoteAttributeValue(adjustStrings(n.value, options), options)
Expand Down
62 changes: 36 additions & 26 deletions tests/css_case/__snapshots__/jsfmt.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
exports[`case.less 1`] = `
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.
// - The \`/*:*/\` comments are just to bust the \`isLikelySCSS\` check.
@IMPORT Keep;
HTML#KeepId.KeepClass,
a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
svg[viewBox] linearGradient,
[HREF=KeepAttrValue]:HOVER::FIRST-letter,
:Not(:NTH-child(2N+1)) {
COLOR: #AAbbCC;
BACKGROUND-image: URL("KeepString");
Expand Down Expand Up @@ -49,7 +52,7 @@ a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
@KeepTopLevelVar: val;
$KeepScssVar: val;
.Keep(@Keep: 12e03PX) WHEN (@Keep=Case) /*:*/ {
.Keep(@Keep: 12e03PX) when (@Keep=Case) /*:*/ {
@KeepVar: KeepName; /*:*/
@{KeepInterpolationVar}: val;
$KeepScssVar: val;
Expand All @@ -59,7 +62,7 @@ $KeepScssVar: val;
prop: val;
}
&Keep & NoKeep {
&Keep & Element {
prop: val;
}
Expand All @@ -71,14 +74,14 @@ $KeepScssVar: val;
.Keep;
.Keep();
.Keep(4PX)!IMPORTANT;
.Keep() WHEN (@Keep=Keep);
.Keep() WHEN (@Keep=12PX);
.Keep() WHEN (@Keep=Keep12PX);
.Keep() when (@Keep=Keep);
.Keep() when (@Keep=12PX);
.Keep() when (@Keep=Keep12PX);
}
.Keep (@Keep) WHEN (lightness(@Keep) >= 12PX) AND (@Keep > 0) {}
.Keep (@Keep) WHEN (lightness(@Keep) != '12PX') AND (@Keep != "12PX") {}
.Keep (@Keep) WHEN (lightness(@Keep) >= Keep12PX) AND (@Keep > @Keep12E5) {}
.Keep (@Keep) when (lightness(@Keep) >= 12PX) and (@Keep > 0) {}
.Keep (@Keep) when (lightness(@Keep) != '12PX') and (@Keep != "12PX") {}
.Keep (@Keep) when (lightness(@Keep) >= Keep12PX) and (@Keep > @Keep12E5) {}
.Keep(@Keep: 12PX; @Keep: @Keep12PX; ...) /*:*/ {}
.Keep(@Keep: '12PX'; @Keep: "12PX"; ...) /*:*/ {}
Expand All @@ -89,15 +92,18 @@ $KeepScssVar: val;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.
// - The \`/*:*/\` comments are just to bust the \`isLikelySCSS\` check.
@import Keep;
html#KeepId.KeepClass,
a[href="KeepAttrValue"]:hover::first-letter,
:not(:nth-child(2n + 1)) {
HTML#KeepId.KeepClass,
a[HREF="KeepAttrValue"]:hover::first-letter,
svg[viewBox] linearGradient,
[HREF="KeepAttrValue"]:hover::first-letter,
:not(:nth-child(2N + 1)) {
color: #aabbcc;
background-image: URL("KeepString");
margin: 5px 0.2e10em;
Expand All @@ -108,15 +114,15 @@ a[href="KeepAttrValue"]:hover::first-letter,
}
@keyframes KeepAnimationName {
from {
FROM {
prop: val;
}
@{KeepInterpolationVar} {
prop: val;
}
to {
TO {
prop: val;
}
}
Expand Down Expand Up @@ -146,7 +152,7 @@ $KeepScssVar: val;
prop: val;
}
&Keep & nokeep {
&Keep & Element {
prop: val;
}
Expand Down Expand Up @@ -186,13 +192,15 @@ $KeepScssVar: val;
exports[`case.scss 1`] = `
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.
@IMPORT Keep;
HTML#KeepId.KeepClass,
a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
svg[viewBox] linearGradient,
:Not(:NTH-child(2N+1)) {
COLOR: #AAbbCC;
BACKGROUND-image: URL("KeepString");
Expand Down Expand Up @@ -245,7 +253,7 @@ $KeepTopLevelVar: val;
prop: val;
}
&Keep & NoKeep {
&Keep & Element {
prop: val;
}
Expand Down Expand Up @@ -274,14 +282,16 @@ $KeepTopLevelVar: val;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.
@import Keep;
html#KeepId.KeepClass,
a[href="KeepAttrValue"]:hover::first-letter,
:not(:nth-child(2n + 1)) {
HTML#KeepId.KeepClass,
a[HREF="KeepAttrValue"]:hover::first-letter,
svg[viewBox] linearGradient,
:not(:nth-child(2N + 1)) {
color: #aabbcc;
background-image: URL("KeepString");
margin: 5px 0.2e10em;
Expand All @@ -292,17 +302,17 @@ a[href="KeepAttrValue"]:hover::first-letter,
}
@keyframes KeepAnimationName {
from {
FROM {
prop: val;
}
#{$KeepInterpolationVar},
#{$Keep + 15px},
#{$Keep + 15PX},
#{$Keep + $Keep15PX} {
prop: val;
}
to {
TO {
prop: val;
}
}
Expand Down Expand Up @@ -334,7 +344,7 @@ $KeepTopLevelVar: val;
prop: val;
}
&Keep & nokeep {
&Keep & Element {
prop: val;
}
Expand Down
21 changes: 12 additions & 9 deletions tests/css_case/case.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.
// - The `/*:*/` comments are just to bust the `isLikelySCSS` check.

@IMPORT Keep;

HTML#KeepId.KeepClass,
a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
svg[viewBox] linearGradient,
[HREF=KeepAttrValue]:HOVER::FIRST-letter,
:Not(:NTH-child(2N+1)) {
COLOR: #AAbbCC;
BACKGROUND-image: URL("KeepString");
Expand Down Expand Up @@ -46,7 +49,7 @@ a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
@KeepTopLevelVar: val;
$KeepScssVar: val;

.Keep(@Keep: 12e03PX) WHEN (@Keep=Case) /*:*/ {
.Keep(@Keep: 12e03PX) when (@Keep=Case) /*:*/ {
@KeepVar: KeepName; /*:*/
@{KeepInterpolationVar}: val;
$KeepScssVar: val;
Expand All @@ -56,7 +59,7 @@ $KeepScssVar: val;
prop: val;
}

&Keep & NoKeep {
&Keep & Element {
prop: val;
}

Expand All @@ -68,14 +71,14 @@ $KeepScssVar: val;
.Keep;
.Keep();
.Keep(4PX)!IMPORTANT;
.Keep() WHEN (@Keep=Keep);
.Keep() WHEN (@Keep=12PX);
.Keep() WHEN (@Keep=Keep12PX);
.Keep() when (@Keep=Keep);
.Keep() when (@Keep=12PX);
.Keep() when (@Keep=Keep12PX);
}

.Keep (@Keep) WHEN (lightness(@Keep) >= 12PX) AND (@Keep > 0) {}
.Keep (@Keep) WHEN (lightness(@Keep) != '12PX') AND (@Keep != "12PX") {}
.Keep (@Keep) WHEN (lightness(@Keep) >= Keep12PX) AND (@Keep > @Keep12E5) {}
.Keep (@Keep) when (lightness(@Keep) >= 12PX) and (@Keep > 0) {}
.Keep (@Keep) when (lightness(@Keep) != '12PX') and (@Keep != "12PX") {}
.Keep (@Keep) when (lightness(@Keep) >= Keep12PX) and (@Keep > @Keep12E5) {}

.Keep(@Keep: 12PX; @Keep: @Keep12PX; ...) /*:*/ {}
.Keep(@Keep: '12PX'; @Keep: "12PX"; ...) /*:*/ {}
Expand Down
6 changes: 4 additions & 2 deletions tests/css_case/case.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Convention in this test file:
// - The case should be preserved for things prefixed with "Keep".
// - The case should always be preserved for function names and property keywords.
// - The case should always be preserved for element names and attribute names
// in selectors, as well as function names and property keywords.
// - Other things should mostly be lowercase.

@IMPORT Keep;

HTML#KeepId.KeepClass,
a[HREF=KeepAttrValue]:HOVER::FIRST-letter,
svg[viewBox] linearGradient,
:Not(:NTH-child(2N+1)) {
COLOR: #AAbbCC;
BACKGROUND-image: URL("KeepString");
Expand Down Expand Up @@ -59,7 +61,7 @@ $KeepTopLevelVar: val;
prop: val;
}

&Keep & NoKeep {
&Keep & Element {
prop: val;
}

Expand Down

0 comments on commit 9fb1a3d

Please sign in to comment.