Handle CSS attribute selector value ending with I flag (#17865)

Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
Konv Suuandfisker authored and GitHub committed 2025-09-10 10:50:40 +08:00
1 parent 5a2b8b4be9
commit 53b83f2058
5 files changed
+66 -12

No files matched your search

+10 -4
View File
@@ -1,19 +1,25 @@
#### Handle attribute selector with case-sensitive flag (#17841 by @kovsu)
#### Handle attribute selector with case-sensitive and uppercase case-insensitive flags (#17841, #17865 by @kovsu)
<!-- prettier-ignore -->
```css
/* Input */
ol[type=a s] {
[type=a s],
[type=a S],
[type=a I] {
list-style-type: lower-alpha;
}
/* Prettier stable */
ol[type="a s"] {
[type="a s"],
[type="a S"],
[type="a I"] {
list-style-type: lower-alpha;
}
/* Prettier main */
ol[type="a" s] {
[type="a" s],
[type="a" S],
[type="a" I] {
list-style-type: lower-alpha;
}
```
+2 -2
View File
@@ -121,8 +121,8 @@ function clean(original, cloned, parent) {
if (original.value) {
let { value } = cloned;
// Parser doesn't understand `s` or `S` flag
if (/\s[sS]$/u.test(value)) {
// Parser only understands the `i` flag
if (/\s[a-zA-Z]$/u.test(value)) {
// Add an extra property to make sure flag is preserved
cloned.__prettier_attribute_selector_flag = value.at(-1);
value = value.slice(0, -1);
+5 -2
View File
@@ -28,9 +28,12 @@ function adjustStrings(value, options) {
function quoteAttributeValue(value, options) {
const quote = options.singleQuote ? "'" : '"';
// Check if the value ends with `s` or `S`, `i` can be solved by postcss
// The selector parser currently only understand `i` flag,
// but not `s`, `S`, and `I`
// To support future flags, we simply check if it's an alphabet letter
// https://github.com/prettier/prettier/pull/17865#discussion_r2332698101
let flag = "";
const match = value.match(/^(?<value>.+?)\s+(?<flag>s|S)$/u);
const match = value.match(/^(?<value>.+?)\s+(?<flag>[a-zA-Z])$/u);
if (match) {
({ value, flag } = match.groups);
}
@@ -74,6 +74,13 @@ input[type="radio" i] {}
img[alt~="person" i][src*="lorem" i] {}
section:has(:not([type="radio" i], [type="checkbox" i])) {}
input[type="radio" I] {}
img[alt~="person" I][src*="lorem" I] {}
section:has(:not([type="radio" I], [type="checkbox" I])) {}
[type=a I] {}
[type="a" I] {}
=====================================output=====================================
input[type='radio' i] {
}
@@ -82,6 +89,18 @@ img[alt~='person' i][src*='lorem' i] {
section:has(:not([type='radio' i], [type='checkbox' i])) {
}
input[type='radio' I] {
}
img[alt~='person' I][src*='lorem' I] {
}
section:has(:not([type='radio' I], [type='checkbox' I])) {
}
[type='a' I] {
}
[type='a' I] {
}
================================================================================
`;
@@ -95,6 +114,13 @@ input[type="radio" i] {}
img[alt~="person" i][src*="lorem" i] {}
section:has(:not([type="radio" i], [type="checkbox" i])) {}
input[type="radio" I] {}
img[alt~="person" I][src*="lorem" I] {}
section:has(:not([type="radio" I], [type="checkbox" I])) {}
[type=a I] {}
[type="a" I] {}
=====================================output=====================================
input[type="radio" i] {
}
@@ -103,6 +129,18 @@ img[alt~="person" i][src*="lorem" i] {
section:has(:not([type="radio" i], [type="checkbox" i])) {
}
input[type="radio" I] {
}
img[alt~="person" I][src*="lorem" I] {
}
section:has(:not([type="radio" I], [type="checkbox" I])) {
}
[type="a" I] {
}
[type="a" I] {
}
================================================================================
`;
@@ -266,9 +304,9 @@ singleQuote: true
[type='a' S] {
}
[type='a x'] {
[type='a' x] {
}
[type='a' x] {
[type='a' x] {
}
================================================================================
@@ -307,9 +345,9 @@ printWidth: 80
[type="a" S] {
}
[type="a x"] {
[type="a" x] {
}
[type="a" x] {
[type="a" x] {
}
================================================================================
@@ -1,3 +1,10 @@
input[type="radio" i] {}
img[alt~="person" i][src*="lorem" i] {}
section:has(:not([type="radio" i], [type="checkbox" i])) {}
input[type="radio" I] {}
img[alt~="person" I][src*="lorem" I] {}
section:has(:not([type="radio" I], [type="checkbox" I])) {}
[type=a I] {}
[type="a" I] {}