@cwcss/crosswind 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +52 -0
- package/dist/bin/cli.js +14615 -0
- package/dist/build.d.ts +24 -0
- package/dist/config.d.ts +5 -0
- package/dist/generator.d.ts +31 -0
- package/dist/index.d.ts +10 -0
- package/dist/parser.d.ts +42 -0
- package/dist/plugin.d.ts +22 -0
- package/dist/preflight-forms.d.ts +5 -0
- package/dist/preflight.d.ts +2 -0
- package/dist/rules-advanced.d.ts +27 -0
- package/dist/rules-effects.d.ts +25 -0
- package/dist/rules-forms.d.ts +7 -0
- package/dist/rules-grid.d.ts +13 -0
- package/dist/rules-interactivity.d.ts +41 -0
- package/dist/rules-layout.d.ts +26 -0
- package/dist/rules-transforms.d.ts +33 -0
- package/dist/rules-typography.d.ts +41 -0
- package/dist/rules.d.ts +39 -0
- package/dist/scanner.d.ts +18 -0
- package/dist/src/index.js +12848 -0
- package/dist/transformer-compile-class.d.ts +37 -0
- package/{src/types.ts → dist/types.d.ts} +17 -86
- package/package.json +2 -16
- package/PLUGIN.md +0 -235
- package/benchmark/framework-comparison.bench.ts +0 -850
- package/bin/cli.ts +0 -365
- package/bin/crosswind +0 -0
- package/bin/headwind +0 -0
- package/build.ts +0 -8
- package/crosswind.config.ts +0 -9
- package/example/comprehensive.html +0 -70
- package/example/index.html +0 -21
- package/example/output.css +0 -236
- package/examples/plugin/README.md +0 -112
- package/examples/plugin/build.ts +0 -32
- package/examples/plugin/src/index.html +0 -34
- package/examples/plugin/src/index.ts +0 -7
- package/headwind +0 -2
- package/src/build.ts +0 -101
- package/src/config.ts +0 -529
- package/src/generator.ts +0 -2173
- package/src/index.ts +0 -10
- package/src/parser.ts +0 -1471
- package/src/plugin.ts +0 -118
- package/src/preflight-forms.ts +0 -229
- package/src/preflight.ts +0 -388
- package/src/rules-advanced.ts +0 -477
- package/src/rules-effects.ts +0 -461
- package/src/rules-forms.ts +0 -103
- package/src/rules-grid.ts +0 -241
- package/src/rules-interactivity.ts +0 -525
- package/src/rules-layout.ts +0 -385
- package/src/rules-transforms.ts +0 -412
- package/src/rules-typography.ts +0 -486
- package/src/rules.ts +0 -809
- package/src/scanner.ts +0 -84
- package/src/transformer-compile-class.ts +0 -275
- package/test/advanced-features.test.ts +0 -911
- package/test/arbitrary.test.ts +0 -396
- package/test/attributify.test.ts +0 -592
- package/test/bracket-syntax.test.ts +0 -1133
- package/test/build.test.ts +0 -99
- package/test/colors.test.ts +0 -934
- package/test/flexbox.test.ts +0 -669
- package/test/generator.test.ts +0 -597
- package/test/grid.test.ts +0 -584
- package/test/layout.test.ts +0 -404
- package/test/modifiers.test.ts +0 -417
- package/test/parser.test.ts +0 -564
- package/test/performance-regression.test.ts +0 -376
- package/test/performance.test.ts +0 -568
- package/test/plugin.test.ts +0 -160
- package/test/scanner.test.ts +0 -94
- package/test/sizing.test.ts +0 -481
- package/test/spacing.test.ts +0 -394
- package/test/transformer-compile-class.test.ts +0 -287
- package/test/transforms.test.ts +0 -448
- package/test/typography.test.ts +0 -632
- package/test/variants-form-states.test.ts +0 -225
- package/test/variants-group-peer.test.ts +0 -66
- package/test/variants-media.test.ts +0 -213
- package/test/variants-positional.test.ts +0 -58
- package/test/variants-pseudo-elements.test.ts +0 -47
- package/test/variants-state.test.ts +0 -62
- package/tsconfig.json +0 -18
package/test/generator.test.ts
DELETED
|
@@ -1,597 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test'
|
|
2
|
-
import { defaultConfig } from '../src/config'
|
|
3
|
-
import { CSSGenerator } from '../src/generator'
|
|
4
|
-
|
|
5
|
-
describe('CSSGenerator', () => {
|
|
6
|
-
describe('Display utilities', () => {
|
|
7
|
-
it('should generate flex utility', () => {
|
|
8
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
9
|
-
gen.generate('flex')
|
|
10
|
-
const css = gen.toCSS(false)
|
|
11
|
-
expect(css).toContain('.flex {')
|
|
12
|
-
expect(css).toContain('display: flex;')
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should generate block utility', () => {
|
|
16
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
17
|
-
gen.generate('block')
|
|
18
|
-
const css = gen.toCSS(false)
|
|
19
|
-
expect(css).toContain('display: block;')
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('should generate hidden utility', () => {
|
|
23
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
24
|
-
gen.generate('hidden')
|
|
25
|
-
const css = gen.toCSS(false)
|
|
26
|
-
expect(css).toContain('display: none;')
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
describe('Flexbox utilities', () => {
|
|
31
|
-
it('should generate flex-col utility', () => {
|
|
32
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
33
|
-
gen.generate('flex-col')
|
|
34
|
-
const css = gen.toCSS(false)
|
|
35
|
-
expect(css).toContain('flex-direction: column;')
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should generate justify-center utility', () => {
|
|
39
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
40
|
-
gen.generate('justify-center')
|
|
41
|
-
const css = gen.toCSS(false)
|
|
42
|
-
expect(css).toContain('justify-content: center;')
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('should generate items-center utility', () => {
|
|
46
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
47
|
-
gen.generate('items-center')
|
|
48
|
-
const css = gen.toCSS(false)
|
|
49
|
-
expect(css).toContain('align-items: center;')
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
describe('Spacing utilities', () => {
|
|
54
|
-
it('should generate padding utility', () => {
|
|
55
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
56
|
-
gen.generate('p-4')
|
|
57
|
-
const css = gen.toCSS(false)
|
|
58
|
-
expect(css).toContain('.p-4 {')
|
|
59
|
-
expect(css).toContain('padding: 1rem;')
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('should generate margin utility', () => {
|
|
63
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
64
|
-
gen.generate('m-2')
|
|
65
|
-
const css = gen.toCSS(false)
|
|
66
|
-
expect(css).toContain('margin: 0.5rem;')
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('should generate horizontal padding', () => {
|
|
70
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
71
|
-
gen.generate('px-4')
|
|
72
|
-
const css = gen.toCSS(false)
|
|
73
|
-
expect(css).toContain('padding-left: 1rem;')
|
|
74
|
-
expect(css).toContain('padding-right: 1rem;')
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('should generate vertical margin', () => {
|
|
78
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
79
|
-
gen.generate('my-8')
|
|
80
|
-
const css = gen.toCSS(false)
|
|
81
|
-
expect(css).toContain('margin-top: 2rem;')
|
|
82
|
-
expect(css).toContain('margin-bottom: 2rem;')
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('should generate specific side padding', () => {
|
|
86
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
87
|
-
gen.generate('pt-2')
|
|
88
|
-
const css = gen.toCSS(false)
|
|
89
|
-
expect(css).toContain('padding-top: 0.5rem;')
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
describe('Sizing utilities', () => {
|
|
94
|
-
it('should generate width utility', () => {
|
|
95
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
96
|
-
gen.generate('w-full')
|
|
97
|
-
const css = gen.toCSS(false)
|
|
98
|
-
expect(css).toContain('width: 100%;')
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('should generate height utility', () => {
|
|
102
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
103
|
-
gen.generate('h-screen')
|
|
104
|
-
const css = gen.toCSS(false)
|
|
105
|
-
expect(css).toContain('height: 100vh;')
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
describe('Color utilities', () => {
|
|
110
|
-
it('should generate background color', () => {
|
|
111
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
112
|
-
gen.generate('bg-gray-500')
|
|
113
|
-
const css = gen.toCSS(false)
|
|
114
|
-
expect(css).toContain('background-color: oklch(55.1% 0.027 264.364);')
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('should generate text color', () => {
|
|
118
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
119
|
-
gen.generate('text-gray-800')
|
|
120
|
-
const css = gen.toCSS(false)
|
|
121
|
-
expect(css).toContain('color: oklch(27.8% 0.033 256.848);')
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('should generate border color', () => {
|
|
125
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
126
|
-
gen.generate('border-gray-300')
|
|
127
|
-
const css = gen.toCSS(false)
|
|
128
|
-
expect(css).toContain('border-color: oklch(87.2% 0.01 258.338);')
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('should handle direct color names', () => {
|
|
132
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
133
|
-
gen.generate('bg-black')
|
|
134
|
-
const css = gen.toCSS(false)
|
|
135
|
-
expect(css).toContain('background-color: #000;')
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('Typography utilities', () => {
|
|
140
|
-
it('should generate font size with line height', () => {
|
|
141
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
142
|
-
gen.generate('text-xl')
|
|
143
|
-
const css = gen.toCSS(false)
|
|
144
|
-
expect(css).toContain('font-size: 1.25rem;')
|
|
145
|
-
expect(css).toContain('line-height: 1.75rem;')
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('should generate font weight', () => {
|
|
149
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
150
|
-
gen.generate('font-bold')
|
|
151
|
-
const css = gen.toCSS(false)
|
|
152
|
-
expect(css).toContain('font-weight: 700;')
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('should generate text alignment', () => {
|
|
156
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
157
|
-
gen.generate('text-center')
|
|
158
|
-
const css = gen.toCSS(false)
|
|
159
|
-
expect(css).toContain('text-align: center;')
|
|
160
|
-
})
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
describe('Border utilities', () => {
|
|
164
|
-
it('should generate border width', () => {
|
|
165
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
166
|
-
gen.generate('border')
|
|
167
|
-
const css = gen.toCSS(false)
|
|
168
|
-
expect(css).toContain('border-width: 1px;')
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
it('should generate border radius', () => {
|
|
172
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
173
|
-
gen.generate('rounded-lg')
|
|
174
|
-
const css = gen.toCSS(false)
|
|
175
|
-
expect(css).toContain('border-radius: 0.5rem;')
|
|
176
|
-
})
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
describe('Pseudo-class variants', () => {
|
|
180
|
-
it('should generate hover variant', () => {
|
|
181
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
182
|
-
gen.generate('hover:bg-gray-500')
|
|
183
|
-
const css = gen.toCSS(false)
|
|
184
|
-
expect(css).toContain('.hover\\:bg-gray-500:hover {')
|
|
185
|
-
expect(css).toContain('background-color: oklch(55.1% 0.027 264.364);')
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it('should generate focus variant', () => {
|
|
189
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
190
|
-
gen.generate('focus:border-gray-300')
|
|
191
|
-
const css = gen.toCSS(false)
|
|
192
|
-
expect(css).toContain('.focus\\:border-gray-300:focus {')
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('should handle multiple variants', () => {
|
|
196
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
197
|
-
gen.generate('hover:focus:bg-gray-500')
|
|
198
|
-
const css = gen.toCSS(false)
|
|
199
|
-
expect(css).toContain(':hover:focus')
|
|
200
|
-
})
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
describe('Responsive variants', () => {
|
|
204
|
-
it('should generate responsive utility', () => {
|
|
205
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
206
|
-
gen.generate('sm:flex')
|
|
207
|
-
const css = gen.toCSS(false)
|
|
208
|
-
expect(css).toContain('@media (min-width: 640px)')
|
|
209
|
-
expect(css).toContain('.sm\\:flex {')
|
|
210
|
-
expect(css).toContain('display: flex;')
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
it('should generate md breakpoint', () => {
|
|
214
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
215
|
-
gen.generate('md:p-8')
|
|
216
|
-
const css = gen.toCSS(false)
|
|
217
|
-
expect(css).toContain('@media (min-width: 768px)')
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
it('should combine responsive and pseudo-class variants', () => {
|
|
221
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
222
|
-
gen.generate('md:hover:bg-gray-500')
|
|
223
|
-
const css = gen.toCSS(false)
|
|
224
|
-
expect(css).toContain('@media (min-width: 768px)')
|
|
225
|
-
expect(css).toContain(':hover')
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
describe('Minification', () => {
|
|
230
|
-
it('should generate minified CSS', () => {
|
|
231
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
232
|
-
gen.generate('p-4')
|
|
233
|
-
gen.generate('m-2')
|
|
234
|
-
const css = gen.toCSS(false, true)
|
|
235
|
-
expect(css).not.toContain('\n')
|
|
236
|
-
expect(css).not.toContain(' ')
|
|
237
|
-
expect(css).toContain('.p-4{padding:1rem}')
|
|
238
|
-
expect(css).toContain('.m-2{margin:0.5rem}')
|
|
239
|
-
})
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
describe('Shortcuts', () => {
|
|
243
|
-
it('should expand shortcuts', () => {
|
|
244
|
-
const config = {
|
|
245
|
-
...defaultConfig,
|
|
246
|
-
shortcuts: {
|
|
247
|
-
btn: 'px-4 py-2 rounded bg-blue-500',
|
|
248
|
-
},
|
|
249
|
-
}
|
|
250
|
-
const gen = new CSSGenerator(config)
|
|
251
|
-
gen.generate('btn')
|
|
252
|
-
const css = gen.toCSS(false)
|
|
253
|
-
expect(css).toContain('padding-left: 1rem;')
|
|
254
|
-
expect(css).toContain('padding-top: 0.5rem;')
|
|
255
|
-
expect(css).toContain('border-radius: 0.25rem;')
|
|
256
|
-
})
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
describe('Blocklist', () => {
|
|
260
|
-
it('should ignore blocklisted classes', () => {
|
|
261
|
-
const config = {
|
|
262
|
-
...defaultConfig,
|
|
263
|
-
blocklist: ['flex'],
|
|
264
|
-
}
|
|
265
|
-
const gen = new CSSGenerator(config)
|
|
266
|
-
gen.generate('flex')
|
|
267
|
-
const css = gen.toCSS(false)
|
|
268
|
-
expect(css).not.toContain('display: flex;')
|
|
269
|
-
})
|
|
270
|
-
})
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
describe('CSSGenerator - Edge Cases', () => {
|
|
274
|
-
it('should handle empty class name', () => {
|
|
275
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
276
|
-
gen.generate('')
|
|
277
|
-
const css = gen.toCSS(false)
|
|
278
|
-
// Should not crash
|
|
279
|
-
expect(css).toBeDefined()
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
it('should handle undefined utility', () => {
|
|
283
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
284
|
-
gen.generate('nonexistent-utility-xyz')
|
|
285
|
-
const css = gen.toCSS(false)
|
|
286
|
-
// Should not generate CSS for unknown utility
|
|
287
|
-
expect(css).not.toContain('nonexistent-utility-xyz')
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('should handle conflicting utilities', () => {
|
|
291
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
292
|
-
gen.generate('p-4')
|
|
293
|
-
gen.generate('p-8')
|
|
294
|
-
const css = gen.toCSS(false)
|
|
295
|
-
// Both should be in CSS (last one wins in cascade)
|
|
296
|
-
expect(css).toContain('padding: 1rem;')
|
|
297
|
-
expect(css).toContain('padding: 2rem;')
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
it('should handle same class generated multiple times', () => {
|
|
301
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
302
|
-
gen.generate('p-4')
|
|
303
|
-
gen.generate('p-4')
|
|
304
|
-
gen.generate('p-4')
|
|
305
|
-
const css = gen.toCSS(false)
|
|
306
|
-
// Should merge into single rule
|
|
307
|
-
const matches = css.match(/\.p-4/g)
|
|
308
|
-
expect(matches?.length).toBe(1)
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
it('should handle very long selector', () => {
|
|
312
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
313
|
-
const longClass = `${'a'.repeat(500)}-4`
|
|
314
|
-
gen.generate(longClass)
|
|
315
|
-
const css = gen.toCSS(false)
|
|
316
|
-
expect(css).toBeDefined()
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
it('should handle special characters in selector escaping', () => {
|
|
320
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
321
|
-
gen.generate('hover:p-4')
|
|
322
|
-
const css = gen.toCSS(false)
|
|
323
|
-
expect(css).toContain('.hover\\:p-4:hover')
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
it('should handle multiple variants on same utility', () => {
|
|
327
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
328
|
-
gen.generate('hover:p-4')
|
|
329
|
-
gen.generate('focus:p-4')
|
|
330
|
-
gen.generate('active:p-4')
|
|
331
|
-
const css = gen.toCSS(false)
|
|
332
|
-
expect(css).toContain(':hover')
|
|
333
|
-
expect(css).toContain(':focus')
|
|
334
|
-
expect(css).toContain(':active')
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
it('should handle important modifier with zero value', () => {
|
|
338
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
339
|
-
gen.generate('!m-0')
|
|
340
|
-
const css = gen.toCSS(false)
|
|
341
|
-
expect(css).toContain('margin: 0 !important;')
|
|
342
|
-
})
|
|
343
|
-
|
|
344
|
-
it('should handle important with arbitrary value', () => {
|
|
345
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
346
|
-
gen.generate('!w-[500px]')
|
|
347
|
-
const css = gen.toCSS(false)
|
|
348
|
-
expect(css).toContain('width: 500px !important;')
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
it('should handle negative zero margin', () => {
|
|
352
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
353
|
-
gen.generate('-m-0')
|
|
354
|
-
const css = gen.toCSS(false)
|
|
355
|
-
expect(css).toContain('margin: 0;') // -0 is normalized to 0
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
it('should handle fraction resulting in zero', () => {
|
|
359
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
360
|
-
gen.generate('w-0/100')
|
|
361
|
-
const css = gen.toCSS(false)
|
|
362
|
-
expect(css).toContain('width: 0%;')
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
it('should handle very small fraction', () => {
|
|
366
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
367
|
-
gen.generate('w-1/1000')
|
|
368
|
-
const css = gen.toCSS(false)
|
|
369
|
-
expect(css).toContain('width: 0.1%;')
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
it('should handle arbitrary value with calc', () => {
|
|
373
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
374
|
-
gen.generate('w-[calc(100vw-2rem)]')
|
|
375
|
-
const css = gen.toCSS(false)
|
|
376
|
-
expect(css).toContain('width: calc(100vw-2rem);')
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
it('should handle arbitrary value with CSS variables', () => {
|
|
380
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
381
|
-
gen.generate('w-[var(--custom-width)]')
|
|
382
|
-
const css = gen.toCSS(false)
|
|
383
|
-
expect(css).toContain('width: var(--custom-width);')
|
|
384
|
-
})
|
|
385
|
-
|
|
386
|
-
it('should handle responsive variant at largest breakpoint', () => {
|
|
387
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
388
|
-
gen.generate('2xl:p-4')
|
|
389
|
-
const css = gen.toCSS(false)
|
|
390
|
-
expect(css).toContain('@media (min-width: 1536px)')
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
it('should handle mixed responsive and pseudo-class variants', () => {
|
|
394
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
395
|
-
gen.generate('md:hover:focus:p-4')
|
|
396
|
-
const css = gen.toCSS(false)
|
|
397
|
-
expect(css).toContain('@media (min-width: 768px)')
|
|
398
|
-
expect(css).toContain(':hover:focus')
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
it('should handle dark mode with responsive', () => {
|
|
402
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
403
|
-
gen.generate('dark:lg:hover:bg-gray-900')
|
|
404
|
-
const css = gen.toCSS(false)
|
|
405
|
-
expect(css).toContain('.dark')
|
|
406
|
-
expect(css).toContain('@media (min-width: 1024px)')
|
|
407
|
-
expect(css).toContain(':hover')
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
it('should handle group variant with multiple states', () => {
|
|
411
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
412
|
-
gen.generate('group-hover:group-focus:bg-blue-500')
|
|
413
|
-
const css = gen.toCSS(false)
|
|
414
|
-
// Should handle last group variant
|
|
415
|
-
expect(css).toContain('.group:')
|
|
416
|
-
})
|
|
417
|
-
|
|
418
|
-
it('should handle peer variant with complex selector', () => {
|
|
419
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
420
|
-
gen.generate('peer-checked:peer-focus:bg-red-500')
|
|
421
|
-
const css = gen.toCSS(false)
|
|
422
|
-
expect(css).toContain('.peer:')
|
|
423
|
-
expect(css).toContain('~')
|
|
424
|
-
})
|
|
425
|
-
|
|
426
|
-
it('should handle child selector utilities', () => {
|
|
427
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
428
|
-
gen.generate('space-x-4')
|
|
429
|
-
const css = gen.toCSS(false)
|
|
430
|
-
expect(css).toContain('> :not([hidden]) ~ :not([hidden])')
|
|
431
|
-
})
|
|
432
|
-
|
|
433
|
-
it('should handle minified output with special characters', () => {
|
|
434
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
435
|
-
gen.generate('hover:focus:bg-[#ff0000]')
|
|
436
|
-
const css = gen.toCSS(false, true)
|
|
437
|
-
expect(css).not.toContain('\n')
|
|
438
|
-
expect(css).not.toContain(' ')
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
it('should handle color with three-digit hex', () => {
|
|
442
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
443
|
-
gen.generate('bg-[#f00]')
|
|
444
|
-
const css = gen.toCSS(false)
|
|
445
|
-
expect(css).toContain('background-color: #f00;')
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
it('should handle color with rgba', () => {
|
|
449
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
450
|
-
gen.generate('bg-[rgba(255,0,0,0.5)]')
|
|
451
|
-
const css = gen.toCSS(false)
|
|
452
|
-
expect(css).toContain('background-color: rgba(255,0,0,0.5);')
|
|
453
|
-
})
|
|
454
|
-
|
|
455
|
-
it('should handle arbitrary property with important', () => {
|
|
456
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
457
|
-
gen.generate('![display:grid]')
|
|
458
|
-
const css = gen.toCSS(false)
|
|
459
|
-
expect(css).toContain('display: grid !important;')
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
it('should handle multiple classes with same selector different properties', () => {
|
|
463
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
464
|
-
gen.generate('p-4')
|
|
465
|
-
gen.generate('m-4')
|
|
466
|
-
const css = gen.toCSS(false)
|
|
467
|
-
expect(css).toContain('padding: 1rem;')
|
|
468
|
-
expect(css).toContain('margin: 1rem;')
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
it('should escape forward slash in fractions', () => {
|
|
472
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
473
|
-
gen.generate('w-1/2')
|
|
474
|
-
const css = gen.toCSS(false)
|
|
475
|
-
expect(css).toContain('.w-1\\/2')
|
|
476
|
-
})
|
|
477
|
-
|
|
478
|
-
it('should escape dots and brackets in arbitrary values', () => {
|
|
479
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
480
|
-
gen.generate('text-[1.5rem]')
|
|
481
|
-
const css = gen.toCSS(false)
|
|
482
|
-
// Check selector escaping for the class (both brackets and dots should be escaped)
|
|
483
|
-
expect(css).toContain('.text-\\[1\\.5rem\\]')
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
it('should handle all variants disabled', () => {
|
|
487
|
-
const config = {
|
|
488
|
-
...defaultConfig,
|
|
489
|
-
variants: {
|
|
490
|
-
...defaultConfig.variants,
|
|
491
|
-
hover: false,
|
|
492
|
-
focus: false,
|
|
493
|
-
},
|
|
494
|
-
}
|
|
495
|
-
const gen = new CSSGenerator(config)
|
|
496
|
-
gen.generate('hover:p-4')
|
|
497
|
-
const css = gen.toCSS(false)
|
|
498
|
-
// Should still generate but without :hover
|
|
499
|
-
expect(css).toBeDefined()
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
it('should handle reset and regenerate', () => {
|
|
503
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
504
|
-
gen.generate('p-4')
|
|
505
|
-
gen.reset()
|
|
506
|
-
gen.generate('m-4')
|
|
507
|
-
const css = gen.toCSS(false)
|
|
508
|
-
expect(css).toContain('margin: 1rem;')
|
|
509
|
-
expect(css).not.toContain('padding: 1rem;')
|
|
510
|
-
})
|
|
511
|
-
|
|
512
|
-
it('should handle preflight CSS with minification', () => {
|
|
513
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
514
|
-
const css = gen.toCSS(true)
|
|
515
|
-
expect(css).toContain('box-sizing')
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
describe('Extreme Edge Cases', () => {
|
|
519
|
-
it('should handle generating the same class 1000 times', () => {
|
|
520
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
521
|
-
for (let i = 0; i < 1000; i++) {
|
|
522
|
-
gen.generate('w-4')
|
|
523
|
-
}
|
|
524
|
-
const css = gen.toCSS(false)
|
|
525
|
-
// Should only have one .w-4 rule
|
|
526
|
-
const matches = css.match(/\.w-4\s*\{/g) || []
|
|
527
|
-
expect(matches.length).toBe(1)
|
|
528
|
-
})
|
|
529
|
-
|
|
530
|
-
it('should handle generating invalid utilities without crashing', () => {
|
|
531
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
532
|
-
expect(() => gen.generate('')).not.toThrow()
|
|
533
|
-
expect(() => gen.generate(' ')).not.toThrow()
|
|
534
|
-
expect(() => gen.generate('invalid-utility-xyz-123')).not.toThrow()
|
|
535
|
-
expect(() => gen.generate('!!!!!')).not.toThrow()
|
|
536
|
-
expect(() => gen.generate(':::::')).not.toThrow()
|
|
537
|
-
})
|
|
538
|
-
|
|
539
|
-
it('should handle generating utilities with null/undefined-like names', () => {
|
|
540
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
541
|
-
expect(() => gen.generate('null')).not.toThrow()
|
|
542
|
-
expect(() => gen.generate('undefined')).not.toThrow()
|
|
543
|
-
expect(() => gen.generate('false')).not.toThrow()
|
|
544
|
-
})
|
|
545
|
-
|
|
546
|
-
it('should handle very long arbitrary values', () => {
|
|
547
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
548
|
-
const longValue = 'a'.repeat(1000)
|
|
549
|
-
gen.generate(`w-[${longValue}]`)
|
|
550
|
-
const css = gen.toCSS(false)
|
|
551
|
-
expect(css).toContain(longValue)
|
|
552
|
-
})
|
|
553
|
-
|
|
554
|
-
it('should handle generating arbitrary property with colon in value', () => {
|
|
555
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
556
|
-
gen.generate('[background-image:url(http://example.com)]')
|
|
557
|
-
const css = gen.toCSS(false)
|
|
558
|
-
expect(css.length).toBeGreaterThan(0)
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
it('should handle malformed arbitrary syntax', () => {
|
|
562
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
563
|
-
expect(() => gen.generate('w-[')).not.toThrow() // Missing closing bracket
|
|
564
|
-
expect(() => gen.generate('w-]')).not.toThrow() // Missing opening bracket
|
|
565
|
-
expect(() => gen.generate('w-[[]]')).not.toThrow() // Double brackets
|
|
566
|
-
expect(() => gen.generate('w-[[]')).not.toThrow() // Unbalanced
|
|
567
|
-
})
|
|
568
|
-
|
|
569
|
-
it('should handle generating with no config theme colors', () => {
|
|
570
|
-
const gen = new CSSGenerator({ ...defaultConfig, theme: { ...defaultConfig.theme, colors: {} } })
|
|
571
|
-
gen.generate('bg-blue-500')
|
|
572
|
-
gen.generate('text-red-500')
|
|
573
|
-
// Should not crash even if colors don't exist
|
|
574
|
-
expect(() => gen.toCSS(false)).not.toThrow()
|
|
575
|
-
})
|
|
576
|
-
|
|
577
|
-
it('should handle generating with no spacing scale', () => {
|
|
578
|
-
const gen = new CSSGenerator({ ...defaultConfig, theme: { ...defaultConfig.theme, spacing: {} } })
|
|
579
|
-
gen.generate('p-4')
|
|
580
|
-
gen.generate('m-8')
|
|
581
|
-
// Should fall back to raw values
|
|
582
|
-
expect(() => gen.toCSS(false)).not.toThrow()
|
|
583
|
-
})
|
|
584
|
-
|
|
585
|
-
it('should handle important modifier on invalid utility', () => {
|
|
586
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
587
|
-
gen.generate('!invalid-utility-name')
|
|
588
|
-
expect(() => gen.toCSS(false)).not.toThrow()
|
|
589
|
-
})
|
|
590
|
-
|
|
591
|
-
it('should handle multiple variants on invalid utility', () => {
|
|
592
|
-
const gen = new CSSGenerator(defaultConfig)
|
|
593
|
-
gen.generate('sm:md:lg:invalid-utility')
|
|
594
|
-
expect(() => gen.toCSS(false)).not.toThrow()
|
|
595
|
-
})
|
|
596
|
-
})
|
|
597
|
-
})
|