diff --git a/changelog_unreleased/css/17841.md b/changelog_unreleased/css/17841.md index 59d1efea8..c438b0932 100644 --- a/changelog_unreleased/css/17841.md +++ b/changelog_unreleased/css/17841.md @@ -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) ```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; } ``` diff --git a/src/language-css/clean.js b/src/language-css/clean.js index ac70c1da6..4508ebf13 100644 --- a/src/language-css/clean.js +++ b/src/language-css/clean.js @@ -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); diff --git a/src/language-css/print/misc.js b/src/language-css/print/misc.js index a2f4d6efd..e6ddc1a1d 100644 --- a/src/language-css/print/misc.js +++ b/src/language-css/print/misc.js @@ -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(/^(?.+?)\s+(?s|S)$/u); + const match = value.match(/^(?.+?)\s+(?[a-zA-Z])$/u); if (match) { ({ value, flag } = match.groups); } diff --git a/tests/format/css/attribute/__snapshots__/format.test.js.snap b/tests/format/css/attribute/__snapshots__/format.test.js.snap index df5ead931..1c3e891e6 100644 --- a/tests/format/css/attribute/__snapshots__/format.test.js.snap +++ b/tests/format/css/attribute/__snapshots__/format.test.js.snap @@ -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] { } ================================================================================ diff --git a/tests/format/css/attribute/insensitive.css b/tests/format/css/attribute/insensitive.css index 46623f35d..ff157952d 100644 --- a/tests/format/css/attribute/insensitive.css +++ b/tests/format/css/attribute/insensitive.css @@ -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] {}