Skip to content

Commit ac39ea5

Browse files
authored
fix: only include pseudo elements that render (#35)
1 parent 6ef8a01 commit ac39ea5

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

src/__tests__/index.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ test("includes pseudo elements", () => {
291291
background: green;
292292
}
293293
294-
div ::before {
294+
.test ::before {
295+
content: "";
295296
display: block;
296297
}
297298
`;
@@ -307,6 +308,10 @@ test("includes pseudo elements", () => {
307308
}}</style>
308309
<span>
309310
<style>@scope{:scope{
311+
&::before {
312+
content: \\"\\";
313+
display: block
314+
}
310315
&::selection {background: blue}
311316
}}</style>
312317
Content
@@ -315,6 +320,42 @@ test("includes pseudo elements", () => {
315320
`);
316321
});
317322

323+
test("pseudo elements only included when they render", () => {
324+
const html = `
325+
<div class="test"><div class="other">Content</div></div>
326+
`;
327+
328+
const styles = `
329+
.test::before { content: "prefix"; color: blue; }
330+
.test::after { content: ""; color: red; }
331+
.test::selection { background: yellow; }
332+
.test::first-line { font-weight: bold; }
333+
334+
.other::before { display: block; }
335+
.other::after { content: none; color: red; }
336+
`;
337+
338+
expect(testHTML(html, styles)).toMatchInlineSnapshot(`
339+
"<div>
340+
<style>@scope{:scope{
341+
&::after {
342+
color: red;
343+
content: \\"\\"
344+
}
345+
&::before {
346+
color: blue;
347+
content: \\"prefix\\"
348+
}
349+
&::first-line {font-weight: bold}
350+
&::selection {background: yellow}
351+
}}</style>
352+
<div>
353+
Content
354+
</div>
355+
</div>"
356+
`);
357+
});
358+
318359
function testHTML(html: string, styles: string = "") {
319360
const div = document.createElement("div");
320361
const style = document.createElement("style");

src/stylesheets.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export function getPseudoElementStyles(
9494
name,
9595
stylesByPseudoElement[name]
9696
);
97-
if (styles) {
97+
if (styles && shouldIncludePseudoElement(name, styles)) {
9898
appliedPseudoElementStyles ||= {};
9999
appliedPseudoElementStyles[name] = styles;
100100
}
@@ -103,6 +103,24 @@ export function getPseudoElementStyles(
103103
return appliedPseudoElementStyles;
104104
}
105105

106+
function shouldIncludePseudoElement(
107+
pseudoName: string,
108+
styles: { [property: string]: string }
109+
): boolean {
110+
if (pseudoName !== "::before" && pseudoName !== "::after") {
111+
// Other pseudo-elements (::selection, ::first-line, etc.) should always be included.
112+
return true;
113+
}
114+
115+
const contentValue = styles.content;
116+
117+
// Pseudo-element renders if:
118+
// - content property exists (not undefined).
119+
// - content: "" (empty string).
120+
// - content is not "none".
121+
return contentValue !== undefined && contentValue !== "none";
122+
}
123+
106124
/**
107125
* Given a stylesheet returns all css rules including rules from
108126
* nested stylesheets such as media queries or supports.

0 commit comments

Comments
 (0)