diff --git a/changelog_unreleased/css/17362.md b/changelog_unreleased/css/17362.md new file mode 100644 index 000000000..d604c822a --- /dev/null +++ b/changelog_unreleased/css/17362.md @@ -0,0 +1,21 @@ +#### Support `@utility` directive for Tailwind (#17362 by @sosukesuzuki) + +This changes supports `@utility` directive for Tailwind CSS V4. + + +```css +/* Input */ +@utility tab-* { + tab-size: --value(--tab-size-*); +} + +/* Prettier stable */ +@utility tab-* { + tab-size: --value(--tab-size- *); +} + +/* Prettier main */ +@utility tab-* { + tab-size: --value(--tab-size-*); +} +``` diff --git a/src/language-css/print/comma-separated-value-group.js b/src/language-css/print/comma-separated-value-group.js index 8f6e2197f..ab4cdce7f 100644 --- a/src/language-css/print/comma-separated-value-group.js +++ b/src/language-css/print/comma-separated-value-group.js @@ -131,6 +131,17 @@ function printCommaSeparatedValueGroup(path, options, print) { continue; } + // Ignore Tailwind `@utility` directive ( https://tailwindcss.com/docs/adding-custom-styles#functional-utilities ) + if ( + insideAtRuleNode(path, "utility") && + iNode.type === "value-word" && + iNextNode && + iNextNode.type === "value-operator" && + iNextNode.value === "*" + ) { + continue; + } + // Ignore after latest node (i.e. before semicolon) if (!iNextNode) { continue; diff --git a/tests/format/css/tailwind/__snapshots__/format.test.js.snap b/tests/format/css/tailwind/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..03352385e --- /dev/null +++ b/tests/format/css/tailwind/__snapshots__/format.test.js.snap @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`utility-directive.css format 1`] = ` +====================================options===================================== +parsers: ["css"] +printWidth: 80 + | printWidth +=====================================input====================================== +@utility tab-* { + tab-size: --value(--tab-size-*); +} + +@utility tab-* { + tab-size: --value(integer); +} + +@utility tab-* { + tab-size: --value([integer]); + tab-size: --value(integer); + tab-size: --value(--tab-size-*); +} + +@utility opacity-* { + opacity: --value([percentage]); + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*); +} + +@utility tab-* { + tab-size: --value(--tab-size-*, integer, [integer]); +} + +@utility opacity-* { + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*, [percentage]); +} + +@utility inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length])); +} + +@utility -inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length]) * -1); +} + +@utility text-* { + font-size: --value(--font-size-*, [length]); + line-height: --modifier(--line-height-*, [length], [*]); +} + +@utility aspect-* { + aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]); +} + +=====================================output===================================== +@utility tab-* { + tab-size: --value(--tab-size-*); +} + +@utility tab-* { + tab-size: --value(integer); +} + +@utility tab-* { + tab-size: --value([integer]); + tab-size: --value(integer); + tab-size: --value(--tab-size-*); +} + +@utility opacity-* { + opacity: --value([percentage]); + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*); +} + +@utility tab-* { + tab-size: --value(--tab-size-*, integer, [integer]); +} + +@utility opacity-* { + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*, [percentage]); +} + +@utility inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length])); +} + +@utility -inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length]) * -1); +} + +@utility text-* { + font-size: --value(--font-size-*, [length]); + line-height: --modifier(--line-height-*, [length], [*]); +} + +@utility aspect-* { + aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]); +} + +================================================================================ +`; diff --git a/tests/format/css/tailwind/format.test.js b/tests/format/css/tailwind/format.test.js new file mode 100644 index 000000000..96617399e --- /dev/null +++ b/tests/format/css/tailwind/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["css"]); diff --git a/tests/format/css/tailwind/utility-directive.css b/tests/format/css/tailwind/utility-directive.css new file mode 100644 index 000000000..2f267db04 --- /dev/null +++ b/tests/format/css/tailwind/utility-directive.css @@ -0,0 +1,45 @@ +@utility tab-* { + tab-size: --value(--tab-size-*); +} + +@utility tab-* { + tab-size: --value(integer); +} + +@utility tab-* { + tab-size: --value([integer]); + tab-size: --value(integer); + tab-size: --value(--tab-size-*); +} + +@utility opacity-* { + opacity: --value([percentage]); + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*); +} + +@utility tab-* { + tab-size: --value(--tab-size-*, integer, [integer]); +} + +@utility opacity-* { + opacity: calc(--value(integer) * 1%); + opacity: --value(--opacity-*, [percentage]); +} + +@utility inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length])); +} + +@utility -inset-* { + inset: calc(--var(--spacing) * --value([percentage], [length]) * -1); +} + +@utility text-* { + font-size: --value(--font-size-*, [length]); + line-height: --modifier(--line-height-*, [length], [*]); +} + +@utility aspect-* { + aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]); +}