From c4053cb22183f53813a4d7097b52dc5bbf3793be Mon Sep 17 00:00:00 2001 From: Vasilii A <3757319+vsn4ik@users.noreply.github.com> Date: Sat, 22 Aug 2026 06:27:43 +0000 Subject: [PATCH] fix(#1347): purge of CSS variables in nested media queries --- .../__tests__/media-queries-variables.test.ts | 45 +++++++++++++++++++ .../__tests__/supports-variables.test.ts | 43 ++++++++++++++++++ .../media_queries_variables.css | 31 +++++++++++++ .../media_queries_variables.html | 4 ++ .../supports-variables/supports_variables.css | 31 +++++++++++++ .../supports_variables.html | 4 ++ packages/purgecss/src/index.ts | 15 ++++++- 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 packages/purgecss/__tests__/media-queries-variables.test.ts create mode 100644 packages/purgecss/__tests__/supports-variables.test.ts create mode 100644 packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.css create mode 100644 packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.html create mode 100644 packages/purgecss/__tests__/test_examples/supports-variables/supports_variables.css create mode 100644 packages/purgecss/__tests__/test_examples/supports-variables/supports_variables.html diff --git a/packages/purgecss/__tests__/media-queries-variables.test.ts b/packages/purgecss/__tests__/media-queries-variables.test.ts new file mode 100644 index 00000000..34977130 --- /dev/null +++ b/packages/purgecss/__tests__/media-queries-variables.test.ts @@ -0,0 +1,45 @@ +import { PurgeCSS, type ResultPurge } from "./../src/index"; +import { ROOT_TEST_EXAMPLES } from "./utils"; + +describe("media queries variables", () => { + let purgecssResult: ResultPurge; + beforeAll(async () => { + const purgecss = await new PurgeCSS().purge({ + content: [ + `${ROOT_TEST_EXAMPLES}media-queries-variables/media_queries_variables.html`, + ], + css: [ + `${ROOT_TEST_EXAMPLES}media-queries-variables/media_queries_variables.css`, + ], + variables: true, + rejected: true, + rejectedCss: true, + }); + purgecssResult = purgecss[0]; + }); + + it("keeps '--font-size-*'", () => { + expect(purgecssResult.css).toContain("--font-size-1:"); + expect(purgecssResult.css).toContain("--font-size-2:"); + expect(purgecssResult.css).toContain("--font-size-3:"); + }); + + it("removes '--unused-font-size-*'", () => { + expect(purgecssResult.rejectedCss).toContain("--unused-font-size-1"); + expect(purgecssResult.rejectedCss).toContain("--unused-font-size-2"); + expect(purgecssResult.css).not.toContain("--unused-font-size-1"); + expect(purgecssResult.css).not.toContain("--unused-font-size-2"); + }); + + it("finds .used-class-*", () => { + expect(purgecssResult.css).toContain(".used-class-1"); + expect(purgecssResult.css).toContain(".used-class-2"); + }); + + it("removes .unused-class-*", () => { + expect(purgecssResult.rejected).toContain(".unused-class-1"); + expect(purgecssResult.rejected).toContain(".unused-class-2"); + expect(purgecssResult.css).not.toContain(".unused-class-1"); + expect(purgecssResult.css).not.toContain(".unused-class-2"); + }); +}); diff --git a/packages/purgecss/__tests__/supports-variables.test.ts b/packages/purgecss/__tests__/supports-variables.test.ts new file mode 100644 index 00000000..268f9a2f --- /dev/null +++ b/packages/purgecss/__tests__/supports-variables.test.ts @@ -0,0 +1,43 @@ +import { PurgeCSS, type ResultPurge } from "./../src/index"; +import { ROOT_TEST_EXAMPLES } from "./utils"; + +describe("supports variables", () => { + let purgecssResult: ResultPurge; + beforeAll(async () => { + const purgecss = await new PurgeCSS().purge({ + content: [ + `${ROOT_TEST_EXAMPLES}supports-variables/supports_variables.html`, + ], + css: [`${ROOT_TEST_EXAMPLES}supports-variables/supports_variables.css`], + variables: true, + rejected: true, + rejectedCss: true, + }); + purgecssResult = purgecss[0]; + }); + + it("keeps '--font-size-*'", () => { + expect(purgecssResult.css).toContain("--font-size-1:"); + expect(purgecssResult.css).toContain("--font-size-2:"); + expect(purgecssResult.css).toContain("--font-size-3:"); + }); + + it("removes '--unused-font-size-*'", () => { + expect(purgecssResult.rejectedCss).toContain("--unused-font-size-1"); + expect(purgecssResult.rejectedCss).toContain("--unused-font-size-2"); + expect(purgecssResult.css).not.toContain("--unused-font-size-1"); + expect(purgecssResult.css).not.toContain("--unused-font-size-2"); + }); + + it("finds .used-class-*", () => { + expect(purgecssResult.css).toContain(".used-class-1"); + expect(purgecssResult.css).toContain(".used-class-2"); + }); + + it("removes .unused-class-*", () => { + expect(purgecssResult.rejected).toContain(".unused-class-1"); + expect(purgecssResult.rejected).toContain(".unused-class-2"); + expect(purgecssResult.css).not.toContain(".unused-class-1"); + expect(purgecssResult.css).not.toContain(".unused-class-2"); + }); +}); diff --git a/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.css b/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.css new file mode 100644 index 00000000..dedd8dbb --- /dev/null +++ b/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.css @@ -0,0 +1,31 @@ +:root { + --font-size-1: 1.5rem; + --font-size-2: 1.5rem; + --font-size-3: 1.5rem; + --unused-font-size-1: 1.5rem; + --unused-font-size-2: 1.5rem; +} + +.used-class-1 { + .used-class-2 { + font-size: var(--font-size-1); + } + + .unused-class-1 { + font-size: var(--unused-font-size-1); + } + + @media (max-width: 768px) { + font-size: var(--font-size-2); + + .used-class-3 { + @media (min-width: 576px) { + font-size: var(--font-size-3); + } + } + + .unused-class-2 { + font-size: var(--unused-font-size-2); + } + } +} diff --git a/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.html b/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.html new file mode 100644 index 00000000..9ae6ee77 --- /dev/null +++ b/packages/purgecss/__tests__/test_examples/media-queries-variables/media_queries_variables.html @@ -0,0 +1,4 @@ +