From f69b51f8ddbfbe8f1d5014b9f837426902819b12 Mon Sep 17 00:00:00 2001 From: AngusMorton Date: Wed, 6 Aug 2025 21:43:53 +1000 Subject: [PATCH] fix: only include pseudo elements that render --- src/__tests__/index.ts | 43 +++++++++++++++++++++++++++++++++++++++++- src/stylesheets.ts | 20 +++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/__tests__/index.ts b/src/__tests__/index.ts index db15a7a..5abcf01 100644 --- a/src/__tests__/index.ts +++ b/src/__tests__/index.ts @@ -291,7 +291,8 @@ test("includes pseudo elements", () => { background: green; } - div ::before { + .test ::before { + content: ""; display: block; } `; @@ -307,6 +308,10 @@ test("includes pseudo elements", () => { }} Content @@ -315,6 +320,42 @@ test("includes pseudo elements", () => { `); }); +test("pseudo elements only included when they render", () => { + const html = ` +
Content
+ `; + + const styles = ` + .test::before { content: "prefix"; color: blue; } + .test::after { content: ""; color: red; } + .test::selection { background: yellow; } + .test::first-line { font-weight: bold; } + + .other::before { display: block; } + .other::after { content: none; color: red; } + `; + + expect(testHTML(html, styles)).toMatchInlineSnapshot(` + "
+ +
+ Content +
+
" + `); +}); + function testHTML(html: string, styles: string = "") { const div = document.createElement("div"); const style = document.createElement("style"); diff --git a/src/stylesheets.ts b/src/stylesheets.ts index 8ff3260..a769b21 100644 --- a/src/stylesheets.ts +++ b/src/stylesheets.ts @@ -94,7 +94,7 @@ export function getPseudoElementStyles( name, stylesByPseudoElement[name] ); - if (styles) { + if (styles && shouldIncludePseudoElement(name, styles)) { appliedPseudoElementStyles ||= {}; appliedPseudoElementStyles[name] = styles; } @@ -103,6 +103,24 @@ export function getPseudoElementStyles( return appliedPseudoElementStyles; } +function shouldIncludePseudoElement( + pseudoName: string, + styles: { [property: string]: string } +): boolean { + if (pseudoName !== "::before" && pseudoName !== "::after") { + // Other pseudo-elements (::selection, ::first-line, etc.) should always be included. + return true; + } + + const contentValue = styles.content; + + // Pseudo-element renders if: + // - content property exists (not undefined). + // - content: "" (empty string). + // - content is not "none". + return contentValue !== undefined && contentValue !== "none"; +} + /** * Given a stylesheet returns all css rules including rules from * nested stylesheets such as media queries or supports.