From 4c4c5a3834552894a99f87e96bb36c6a002abc60 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Sat, 5 Sep 2020 00:36:50 +0200 Subject: [PATCH] Fix purging in 1.8 (#2320) * re-add missing `@layer`'s for responsive rules * use toMatchCss for better diffing * do not wrap user `@responsive` rules in an `@layer` --- __tests__/purgeUnusedStyles.test.js | 8 +++--- src/lib/substituteResponsiveAtRules.js | 36 +++++++++++++++++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/__tests__/purgeUnusedStyles.test.js b/__tests__/purgeUnusedStyles.test.js index 6fa108d14..7929d9735 100644 --- a/__tests__/purgeUnusedStyles.test.js +++ b/__tests__/purgeUnusedStyles.test.js @@ -430,7 +430,7 @@ test( 'utf8' ) - expect(result.css).toBe(expected) + expect(result.css).toMatchCss(expected) }) }) ) @@ -457,7 +457,7 @@ test('does not purge if the array is empty', () => { 'utf8' ) - expect(result.css).toBe(expected) + expect(result.css).toMatchCss(expected) }) }) ) @@ -482,7 +482,7 @@ test('does not purge if explicitly disabled', () => { 'utf8' ) - expect(result.css).toBe(expected) + expect(result.css).toMatchCss(expected) }) }) ) @@ -507,7 +507,7 @@ test('does not purge if purge is simply false', () => { 'utf8' ) - expect(result.css).toBe(expected) + expect(result.css).toMatchCss(expected) }) }) ) diff --git a/src/lib/substituteResponsiveAtRules.js b/src/lib/substituteResponsiveAtRules.js index 92cc412d7..b7bfe0d67 100644 --- a/src/lib/substituteResponsiveAtRules.js +++ b/src/lib/substituteResponsiveAtRules.js @@ -4,16 +4,31 @@ import cloneNodes from '../util/cloneNodes' import buildMediaQuery from '../util/buildMediaQuery' import buildSelectorVariant from '../util/buildSelectorVariant' +function isLayer(node) { + if (Array.isArray(node)) { + return node.length === 1 && isLayer(node[0]) + } + return node.type === 'atrule' && node.name === 'layer' +} + +function layerNodes(nodes) { + return isLayer(nodes) ? nodes[0].nodes : nodes +} + export default function(config) { return function(css) { - // Store the `layer` for each responsive at-rule directly on the at-rule for later reference. + // Wrap any `responsive` rules with a copy of their parent `layer` to + // ensure the layer isn't lost when copying to the `screens` location. css.walkAtRules('layer', layerAtRule => { const layer = layerAtRule.params layerAtRule.walkAtRules('responsive', responsiveAtRule => { - responsiveAtRule.__tailwind = { - ...responsiveAtRule.__tailwind, - layer, - } + const nestedlayerAtRule = postcss.atRule({ + name: 'layer', + params: layer, + }) + nestedlayerAtRule.prepend(responsiveAtRule.nodes) + responsiveAtRule.removeAll() + responsiveAtRule.prepend(nestedlayerAtRule) }) }) @@ -27,7 +42,16 @@ export default function(config) { css.walkAtRules('responsive', atRule => { const nodes = atRule.nodes responsiveRules.append(...cloneNodes(nodes)) - atRule.before(nodes) + + // If the parent is already a `layer` (this is true for anything coming from + // a plugin, including core plugins) we don't want to create a double nested + // layer, so only insert the layer children. If there is no parent layer, + // preserve the layer information when inserting the nodes. + if (isLayer(atRule.parent)) { + atRule.before(layerNodes(nodes)) + } else { + atRule.before(nodes) + } atRule.remove() })