Skip to content

Commit e1091f8

Browse files
committed
fix: migrated from \css-tree\ to \postcss\ to solve build issues
1 parent da1aa54 commit e1091f8

32 files changed

+1510
-963
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
uses: actions/setup-node@v4
6161
with:
6262
node-version: lts/*
63-
registry-url: "https://registry.npmjs.org"
63+
registry-url: 'https://registry.npmjs.org'
6464

6565
- name: Get current version
6666
id: current_version

bun.lock

Lines changed: 48 additions & 9 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
}
1919
},
2020
"dependencies": {
21-
"css-tree": "^3.1.0",
2221
"html-to-text": "^9.0.5",
2322
"parse5": "^8.0.0",
23+
"postcss": "^8.5.6",
24+
"postcss-value-parser": "^4.2.0",
2425
"tailwindcss": "^4.1.17"
2526
},
2627
"optionalDependencies": {
@@ -36,9 +37,9 @@
3637
"@sveltejs/package": "^2.5.4",
3738
"@sveltejs/vite-plugin-svelte": "^6.2.1",
3839
"@tailwindcss/vite": "^4.1.17",
39-
"@types/css-tree": "^2.3.11",
4040
"@types/html-to-text": "^9.0.4",
4141
"@types/node": "^24.10.1",
42+
"@vitest/coverage-v8": "^4.0.14",
4243
"eslint": "^9.39.1",
4344
"eslint-config-prettier": "^10.1.8",
4445
"eslint-plugin-svelte": "^3.13.0",

src/lib/components/__tests__/__snapshots__/end-to-end.test.ts.snap

Lines changed: 58 additions & 2 deletions
Large diffs are not rendered by default.

src/lib/render/index.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { render as svelteRender } from 'svelte/server';
22
import { parse, serialize, type DefaultTreeAdapterTypes } from 'parse5';
3+
import postcss from 'postcss';
34
import { walk } from './utils/html/walk.js';
45
import { setupTailwind } from './utils/tailwindcss/setup-tailwind.js';
56
import type { Config } from 'tailwindcss';
67
import { sanitizeStyleSheet } from './utils/css/sanitize-stylesheet.js';
78
import { extractRulesPerClass } from './utils/css/extract-rules-per-class.js';
89
import { getCustomProperties } from './utils/css/get-custom-properties.js';
9-
import { generate, List, type CssNode, type StyleSheet } from 'css-tree';
1010
import { sanitizeNonInlinableRules } from './utils/css/sanitize-non-inlinable-rules.js';
1111
import { addInlinedStylesToElement } from './utils/tailwindcss/add-inlined-styles-to-element.js';
1212
import { isValidNode } from './utils/html/is-valid-node.js';
@@ -108,10 +108,11 @@ export default class Renderer {
108108

109109
const customProperties = getCustomProperties(styleSheet);
110110

111-
const nonInlineStyles: StyleSheet = {
112-
type: 'StyleSheet',
113-
children: new List<CssNode>().fromArray(Array.from(nonInlinableRules.values()))
114-
};
111+
// Create a new Root for non-inline styles
112+
const nonInlineStyles = postcss.root();
113+
for (const rule of nonInlinableRules.values()) {
114+
nonInlineStyles.append(rule.clone());
115+
}
115116
sanitizeNonInlinableRules(nonInlineStyles);
116117

117118
const hasNonInlineStylesToApply = nonInlinableRules.size > 0;
@@ -148,7 +149,7 @@ export default class Renderer {
148149
appliedNonInlineStyles = true;
149150
serialized = serialized.replace(
150151
'<head>',
151-
'<head>' + '<style>' + generate(nonInlineStyles) + '</style>'
152+
'<head>' + '<style>' + nonInlineStyles.toString() + '</style>'
152153
);
153154
}
154155

src/lib/render/utils/css/__snapshots__/extract-rules-per-class.spec.ts.snap

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,48 @@
22

33
exports[`extractRulesPerClass() > handles a mix of inlinable and non-inlinable utilities 1`] = `
44
{
5-
"bg-red-500": ".bg-red-500{background-color:var(--color-red-500)}",
6-
"text-center": ".text-center{text-align:center}",
7-
"w-full": ".w-full{width:100%}",
5+
"bg-red-500": ".bg-red-500 {
6+
background-color: var(--color-red-500);
7+
}",
8+
"text-center": ".text-center {
9+
text-align: center;
10+
}",
11+
"w-full": ".w-full {
12+
width: 100%;
13+
}",
814
}
915
`;
1016

1117
exports[`extractRulesPerClass() > handles a mix of inlinable and non-inlinable utilities 2`] = `
1218
{
13-
"lg:w-1/2": ".lg\\:w-1\\/2{@media (width>=64rem){width:calc(1/2*100%)}}",
19+
"lg:w-1/2": ".lg\\:w-1\\/2 {
20+
@media (width >= 64rem) {
21+
width: calc(1/2 * 100%);
22+
}
23+
}",
1424
}
1525
`;
1626

1727
exports[`extractRulesPerClass() > handles non-inlinable utilities 1`] = `{}`;
1828

1929
exports[`extractRulesPerClass() > handles non-inlinable utilities 2`] = `
2030
{
21-
"lg:w-1/2": ".lg\\:w-1\\/2{@media (width>=64rem){width:calc(1/2*100%)}}",
31+
"lg:w-1/2": ".lg\\:w-1\\/2 {
32+
@media (width >= 64rem) {
33+
width: calc(1/2 * 100%);
34+
}
35+
}",
2236
}
2337
`;
2438

2539
exports[`extractRulesPerClass() > works with just inlinable utilities 1`] = `
2640
{
27-
"bg-red-500": ".bg-red-500{background-color:var(--color-red-500)}",
28-
"text-center": ".text-center{text-align:center}",
41+
"bg-red-500": ".bg-red-500 {
42+
background-color: var(--color-red-500);
43+
}",
44+
"text-center": ".text-center {
45+
text-align: center;
46+
}",
2947
}
3048
`;
3149

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`makeInlineStylesFor() > does basic local variable resolution 1`] = `"background-color: #3490dc ;color: #fff ;padding: 0.5rem 1rem ;border-radius: 0.25rem ;"`;
3+
exports[`makeInlineStylesFor() > does basic local variable resolution 1`] = `"background-color: #3490dc ;color: #fff ;padding: 0.5rem 1rem ;border-radius: 0.25rem ;"`;
44

55
exports[`makeInlineStylesFor() > works in simple use case 1`] = `"background-color: #f56565 ;width: 100% ;"`;
Lines changed: 185 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,196 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`resolveAllCSSVariables > handles deeply nested var() functions with complex parentheses 1`] = `":root{--primary: blue;--secondary: red;--fallback: green;--size: 20px}.box{color:blue;width:20px;border:1px solid black;--r: 100;--b: 10;background:rgb(100,0,10)}"`;
3+
exports[`resolveAllCSSVariables > handles deeply nested var() functions with complex parentheses 1`] = `
4+
":root {
5+
--primary: blue;
6+
--secondary: red;
7+
--fallback: green;
8+
--size: 20px;
9+
}
410
5-
exports[`resolveAllCSSVariables > handles nested var() functions in fallbacks 1`] = `":root{--fallback-width: 300px}.box{width:300px;height:250px}"`;
11+
.box {
12+
color: blue;
13+
width: 20px;
14+
border: 1px solid black;
15+
--r: 100;
16+
--b: 10;
17+
background: rgb(100, 0, 10);
18+
}"
19+
`;
620

7-
exports[`resolveAllCSSVariables > ignores @layer (properties) defined for browser compatibility 1`] = `"/*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */@layer properties;@layer theme,base,components,utilities;@layer theme{:root,:host{--color-red-500: oklch(63.7% 0.237 25.331);--color-blue-400: oklch(70.7% 0.165 254.624);--color-blue-600: oklch(54.6% 0.245 262.881);--color-gray-200: oklch(92.8% 0.006 264.531);--color-black: #000;--color-white: #fff;--spacing: 0.25rem;--text-sm: 0.875rem;--text-sm--line-height: calc(1.25 / 0.875);--radius-md: 0.375rem}}@layer utilities{.mt-8{margin-top:calc(0.25rem*8)}.rounded-md{border-radius:0.375rem}.bg-blue-600{background-color:oklch(54.6%0.245 262.881)}.bg-red-500{background-color:oklch(63.7%0.237 25.331)}.bg-white{background-color:#fff}.p-4{padding:calc(0.25rem*4)}.px-3{padding-inline:calc(0.25rem*3)}.py-2{padding-block:calc(0.25rem*2)}.text-sm{font-size:0.875rem;line-height:calc(1.25/0.875)}.text-\\\\[14px\\\\]{font-size:14px}.leading-\\\\[24px\\\\]{--tw-leading: 24px;line-height:24px}.text-black{color:#000}.text-blue-400{color:oklch(70.7%0.165 254.624)}.text-blue-600{color:oklch(54.6%0.245 262.881)}.text-gray-200{color:oklch(92.8%0.006 264.531)}.no-underline{text-decoration-line:none}}@property --tw-leading{syntax:"*";inherits:false}@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,::before,::after,::backdrop{--tw-leading: initial}}}"`;
21+
exports[`resolveAllCSSVariables > handles nested var() functions in fallbacks 1`] = `
22+
":root {
23+
--fallback-width: 300px;
24+
}
825
9-
exports[`resolveAllCSSVariables > keeps variable usages if it cant find their declaration 1`] = `".box{width:var(--width)}"`;
26+
.box {
27+
width: 300px;
28+
height: 250px;
29+
}"
30+
`;
1031

11-
exports[`resolveAllCSSVariables > uses fallback values when variable definition is not found 1`] = `".box{width:150px;height:200px;margin:10px 20px}"`;
32+
exports[`resolveAllCSSVariables > ignores @layer (properties) defined for browser compatibility 1`] = `
33+
"/*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */
34+
@layer properties;
35+
@layer theme, base, components, utilities;
36+
@layer theme {
37+
:root, :host {
38+
--color-red-500: oklch(63.7% 0.237 25.331);
39+
--color-blue-400: oklch(70.7% 0.165 254.624);
40+
--color-blue-600: oklch(54.6% 0.245 262.881);
41+
--color-gray-200: oklch(92.8% 0.006 264.531);
42+
--color-black: #000;
43+
--color-white: #fff;
44+
--spacing: 0.25rem;
45+
--text-sm: 0.875rem;
46+
--text-sm--line-height: calc(1.25 / 0.875);
47+
--radius-md: 0.375rem;
48+
}
49+
}
50+
@layer utilities {
51+
.mt-8 {
52+
margin-top: calc(0.25rem * 8);
53+
}
54+
.rounded-md {
55+
border-radius: 0.375rem;
56+
}
57+
.bg-blue-600 {
58+
background-color: oklch(54.6% 0.245 262.881);
59+
}
60+
.bg-red-500 {
61+
background-color: oklch(63.7% 0.237 25.331);
62+
}
63+
.bg-white {
64+
background-color: #fff;
65+
}
66+
.p-4 {
67+
padding: calc(0.25rem * 4);
68+
}
69+
.px-3 {
70+
padding-inline: calc(0.25rem * 3);
71+
}
72+
.py-2 {
73+
padding-block: calc(0.25rem * 2);
74+
}
75+
.text-sm {
76+
font-size: 0.875rem;
77+
line-height: calc(1.25 / 0.875);
78+
}
79+
.text-\\[14px\\] {
80+
font-size: 14px;
81+
}
82+
.leading-\\[24px\\] {
83+
--tw-leading: 24px;
84+
line-height: 24px;
85+
}
86+
.text-black {
87+
color: #000;
88+
}
89+
.text-blue-400 {
90+
color: oklch(70.7% 0.165 254.624);
91+
}
92+
.text-blue-600 {
93+
color: oklch(54.6% 0.245 262.881);
94+
}
95+
.text-gray-200 {
96+
color: oklch(92.8% 0.006 264.531);
97+
}
98+
.no-underline {
99+
text-decoration-line: none;
100+
}
101+
}
102+
@property --tw-leading {
103+
syntax: "*";
104+
inherits: false;
105+
}
106+
@layer properties {
107+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
108+
*, ::before, ::after, ::backdrop {
109+
--tw-leading: initial;
110+
}
111+
}
112+
}
113+
"
114+
`;
12115

13-
exports[`resolveAllCSSVariables > works for variables across different CSS layers 1`] = `"@layer base{:root{--width: 100px}}@layer utilities{.box{width:100px}}"`;
116+
exports[`resolveAllCSSVariables > keeps variable usages if it cant find their declaration 1`] = `
117+
".box {
118+
width: var(--width);
119+
}"
120+
`;
14121

15-
exports[`resolveAllCSSVariables > works with a variable set in a layer, and used in another through a media query 1`] = `"@layer theme{:root{--color-blue-300: blue}}@layer utilities{.sm\\\\:bg-blue-300{@media (width>=40rem){background-color:blue}}}"`;
122+
exports[`resolveAllCSSVariables > uses fallback values when variable definition is not found 1`] = `
123+
".box {
124+
width: 150px;
125+
height: 200px;
126+
margin: 10px 20px;
127+
}"
128+
`;
16129

17-
exports[`resolveAllCSSVariables > works with multiple variables in the same declaration 1`] = `":root{--top: 101px;--bottom: 102px;--right: 103px;--left: 104px}.box{margin:101px 103px 102px 104px}"`;
130+
exports[`resolveAllCSSVariables > works for variables across different CSS layers 1`] = `
131+
"@layer base {
132+
:root {
133+
--width: 100px;
134+
}
135+
}
18136
19-
exports[`resolveAllCSSVariables > works with simple css variables on a :root 1`] = `":root{--width: 100px}.box{width:100px}"`;
137+
@layer utilities {
138+
.box {
139+
width: 100px;
140+
}
141+
}"
142+
`;
20143

21-
exports[`resolveAllCSSVariables > works with variables set in the same rule 1`] = `".box{--width: 200px;width:200px}@media (min-width:1280px){.xl\\\\:bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94/1)}}"`;
144+
exports[`resolveAllCSSVariables > works with a variable set in a layer, and used in another through a media query 1`] = `
145+
"@layer theme {
146+
:root {
147+
--color-blue-300: blue;
148+
}
149+
}
150+
151+
@layer utilities {
152+
.sm\\:bg-blue-300 {
153+
@media (width >= 40rem) {
154+
background-color: blue;
155+
}
156+
}
157+
}"
158+
`;
159+
160+
exports[`resolveAllCSSVariables > works with multiple variables in the same declaration 1`] = `
161+
":root {
162+
--top: 101px;
163+
--bottom: 102px;
164+
--right: 103px;
165+
--left: 104px;
166+
}
167+
168+
.box {
169+
margin: 101px 103px 102px 104px;
170+
}"
171+
`;
172+
173+
exports[`resolveAllCSSVariables > works with simple css variables on a :root 1`] = `
174+
":root {
175+
--width: 100px;
176+
}
177+
178+
.box {
179+
width: 100px;
180+
}"
181+
`;
182+
183+
exports[`resolveAllCSSVariables > works with variables set in the same rule 1`] = `
184+
".box {
185+
--width: 200px;
186+
width: 200px;
187+
}
188+
189+
@media (min-width: 1280px) {
190+
.xl\\:bg-green-500 {
191+
--tw-bg-opacity: 1;
192+
background-color: rgb(34 197 94 / 1)
193+
}
194+
}
195+
"
196+
`;
Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`resolveCalcExpressions() > does not modify complex calc expressions 1`] = `".px-3{padding-inline:calc(0.25rem*(3 + 1px))}.py-2{padding-block:calc(0.25rem*(2 + 1px))}"`;
3+
exports[`resolveCalcExpressions() > does not modify complex calc expressions 1`] = `
4+
"
5+
.px-3{padding-inline:calc(0.25rem*(3 + 1px))}
6+
.py-2{padding-block:calc(0.25rem*(2 + 1px))}
7+
"
8+
`;
49

5-
exports[`resolveCalcExpressions() > resolves calc expressions repeating decimals 1`] = `".w-1/3{width:33.33333333333333%}"`;
10+
exports[`resolveCalcExpressions() > resolves calc expressions repeating decimals 1`] = `
11+
"
12+
.w-1/3 { width: 33.33333333333333%; }
13+
"
14+
`;
615

7-
exports[`resolveCalcExpressions() > resolves spacing calc expressions from tailwind v4 1`] = `".px-3{padding-inline:0.75rem}.py-2{padding-block:0.5rem}"`;
16+
exports[`resolveCalcExpressions() > resolves spacing calc expressions from tailwind v4 1`] = `
17+
"
18+
.px-3{padding-inline:0.75rem}
19+
.py-2{padding-block:0.5rem}
20+
"
21+
`;

0 commit comments

Comments
 (0)