From 4ff383fbbe6dddfc937a1611a7e34a43302e1d62 Mon Sep 17 00:00:00 2001 From: Brad Cornes Date: Mon, 16 Aug 2021 17:25:30 +0100 Subject: [PATCH] Fix malformed keyframes when using class variants (#5223) --- src/plugins/animation.js | 1 - src/util/isKeyframeRule.js | 3 +++ src/util/pluginUtils.js | 4 ++++ src/util/processPlugins.js | 5 +---- tests/jit/animations.test.css | 32 ++++++++++++++++++++++++++++++++ tests/jit/animations.test.html | 3 +++ tests/jit/animations.test.js | 30 ++++++++++++++++++++++++++++++ 7 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/util/isKeyframeRule.js create mode 100644 tests/jit/animations.test.css create mode 100644 tests/jit/animations.test.html create mode 100644 tests/jit/animations.test.js diff --git a/src/plugins/animation.js b/src/plugins/animation.js index 40cc10168..e028fb1de 100644 --- a/src/plugins/animation.js +++ b/src/plugins/animation.js @@ -11,7 +11,6 @@ export default function () { { [`@keyframes ${prefixName(key)}`]: value, }, - { respectVariants: false }, ], ] }) diff --git a/src/util/isKeyframeRule.js b/src/util/isKeyframeRule.js new file mode 100644 index 000000000..a745e979b --- /dev/null +++ b/src/util/isKeyframeRule.js @@ -0,0 +1,3 @@ +export default function isKeyframeRule(rule) { + return rule.parent && rule.parent.type === 'atrule' && /keyframes$/.test(rule.parent.name) +} diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index 8d67f35e0..5babd0c36 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -3,6 +3,7 @@ import postcss from 'postcss' import createColor from 'color' import escapeCommas from './escapeCommas' import { withAlphaValue } from './withAlphaVariable' +import isKeyframeRule from './isKeyframeRule' export function applyPseudoToMarker(selector, marker, state, join) { let states = [state] @@ -72,6 +73,9 @@ export function updateLastClasses(selectors, updateClass) { export function transformAllSelectors(transformSelector, { wrap, withRule } = {}) { return ({ container }) => { container.walkRules((rule) => { + if (isKeyframeRule(rule)) { + return rule + } let transformed = rule.selector.split(',').map(transformSelector).join(',') rule.selector = transformed if (withRule) { diff --git a/src/util/processPlugins.js b/src/util/processPlugins.js index b11613c6b..afd5d51cf 100644 --- a/src/util/processPlugins.js +++ b/src/util/processPlugins.js @@ -10,6 +10,7 @@ import wrapWithVariants from '../util/wrapWithVariants' import cloneNodes from '../util/cloneNodes' import transformThemeValue from './transformThemeValue' import nameClass from '../util/nameClass' +import isKeyframeRule from '../util/isKeyframeRule' function parseStyles(styles) { if (!Array.isArray(styles)) { @@ -28,10 +29,6 @@ function wrapWithLayer(rules, layer) { .append(cloneNodes(Array.isArray(rules) ? rules : [rules])) } -function isKeyframeRule(rule) { - return rule.parent && rule.parent.type === 'atrule' && /keyframes$/.test(rule.parent.name) -} - export default function (plugins, config) { const pluginBaseStyles = [] const pluginComponents = [] diff --git a/tests/jit/animations.test.css b/tests/jit/animations.test.css new file mode 100644 index 000000000..78244c7dd --- /dev/null +++ b/tests/jit/animations.test.css @@ -0,0 +1,32 @@ +@keyframes spin { + to { + transform: rotate(360deg); + } +} +.animate-spin { + animation: spin 1s linear infinite; +} +@keyframes ping { + 75%, + 100% { + transform: scale(2); + opacity: 0; + } +} +.hover\:animate-ping:hover { + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} +@keyframes bounce { + 0%, + 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } +} +.group:hover .group-hover\:animate-bounce { + animation: bounce 1s infinite; +} diff --git a/tests/jit/animations.test.html b/tests/jit/animations.test.html new file mode 100644 index 000000000..3d5a919e6 --- /dev/null +++ b/tests/jit/animations.test.html @@ -0,0 +1,3 @@ +
+
+
diff --git a/tests/jit/animations.test.js b/tests/jit/animations.test.js new file mode 100644 index 000000000..7ddedcf49 --- /dev/null +++ b/tests/jit/animations.test.js @@ -0,0 +1,30 @@ +import postcss from 'postcss' +import fs from 'fs' +import path from 'path' +import tailwind from '../../src/jit/index.js' + +function run(input, config = {}) { + return postcss(tailwind(config)).process(input, { + from: path.resolve(__filename), + }) +} + +test('animations', () => { + let config = { + darkMode: 'class', + mode: 'jit', + purge: [path.resolve(__dirname, './animations.test.html')], + corePlugins: {}, + theme: {}, + plugins: [], + } + + let css = `@tailwind utilities` + + return run(css, config).then((result) => { + let expectedPath = path.resolve(__dirname, './animations.test.css') + let expected = fs.readFileSync(expectedPath, 'utf8') + + expect(result.css).toMatchFormattedCss(expected) + }) +})