typography-stylecss 0.7.2

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.
@@ -0,0 +1,1442 @@
1
+ const path = require('path')
2
+ const tailwind = require('tailwindcss')
3
+ const postcss = require('postcss')
4
+ const typographyPlugin = require('.')
5
+
6
+ let html = String.raw
7
+ let css = String.raw
8
+
9
+ let vars = `
10
+ --tw-border-spacing-x: 0;
11
+ --tw-border-spacing-y: 0;
12
+ --tw-translate-x: 0;
13
+ --tw-translate-y: 0;
14
+ --tw-rotate: 0;
15
+ --tw-skew-x: 0;
16
+ --tw-skew-y: 0;
17
+ --tw-scale-x: 1;
18
+ --tw-scale-y: 1;
19
+ --tw-pan-x: ;
20
+ --tw-pan-y: ;
21
+ --tw-pinch-zoom: ;
22
+ --tw-scroll-snap-strictness: proximity;
23
+ --tw-ordinal: ;
24
+ --tw-slashed-zero: ;
25
+ --tw-numeric-figure: ;
26
+ --tw-numeric-spacing: ;
27
+ --tw-numeric-fraction: ;
28
+ --tw-ring-inset: ;
29
+ --tw-ring-offset-width: 0px;
30
+ --tw-ring-offset-color: #fff;
31
+ --tw-ring-color: rgb(59 130 246 / 0.5);
32
+ --tw-ring-offset-shadow: 0 0 #0000;
33
+ --tw-ring-shadow: 0 0 #0000;
34
+ --tw-shadow: 0 0 #0000;
35
+ --tw-shadow-colored: 0 0 #0000;
36
+ --tw-blur: ;
37
+ --tw-brightness: ;
38
+ --tw-contrast: ;
39
+ --tw-grayscale: ;
40
+ --tw-hue-rotate: ;
41
+ --tw-invert: ;
42
+ --tw-saturate: ;
43
+ --tw-sepia: ;
44
+ --tw-drop-shadow: ;
45
+ --tw-backdrop-blur: ;
46
+ --tw-backdrop-brightness: ;
47
+ --tw-backdrop-contrast: ;
48
+ --tw-backdrop-grayscale: ;
49
+ --tw-backdrop-hue-rotate: ;
50
+ --tw-backdrop-invert: ;
51
+ --tw-backdrop-opacity: ;
52
+ --tw-backdrop-saturate: ;
53
+ --tw-backdrop-sepia: ;
54
+ `
55
+ let defaults = css`
56
+ *,
57
+ ::before,
58
+ ::after {
59
+ ${vars}
60
+ }
61
+ ::backdrop {
62
+ ${vars}
63
+ }
64
+ `
65
+
66
+ function run(config, plugin = tailwind) {
67
+ let { currentTestName } = expect.getState()
68
+ config = {
69
+ ...{ plugins: [typographyPlugin], corePlugins: { preflight: false } },
70
+ ...config,
71
+ }
72
+
73
+ return postcss(plugin(config)).process(
74
+ ['@tailwind base;', '@tailwind components;', '@tailwind utilities'].join('\n'),
75
+ {
76
+ from: `${path.resolve(__filename)}?test=${currentTestName}`,
77
+ }
78
+ )
79
+ }
80
+
81
+ test('specificity is reduced with :where', async () => {
82
+ let config = {
83
+ content: [{ raw: html`<div class="prose"></div>` }],
84
+ theme: {
85
+ typography: {
86
+ DEFAULT: {
87
+ css: [
88
+ {
89
+ color: 'var(--tw-prose-body)',
90
+ maxWidth: '65ch',
91
+ '[class~="lead"]': {
92
+ color: 'var(--tw-prose-lead)',
93
+ },
94
+ strong: {
95
+ color: 'var(--tw-prose-bold)',
96
+ fontWeight: '600',
97
+ },
98
+ 'ol[type="A"]': {
99
+ listStyleType: 'upper-alpha',
100
+ },
101
+ 'blockquote p:first-of-type::before': {
102
+ content: 'open-quote',
103
+ },
104
+ 'blockquote p:last-of-type::after': {
105
+ content: 'close-quote',
106
+ },
107
+ 'h4 strong': {
108
+ fontWeight: '700',
109
+ },
110
+ 'figure > *': {
111
+ margin: 0,
112
+ },
113
+ 'ol > li::marker': {
114
+ fontWeight: '400',
115
+ color: 'var(--tw-prose-counters)',
116
+ },
117
+ '> ul > li p': {
118
+ marginTop: '16px',
119
+ marginBottom: '16px',
120
+ },
121
+ 'code::before': {
122
+ content: '"&#96;"',
123
+ },
124
+ 'code::after': {
125
+ content: '"&#96;"',
126
+ },
127
+ },
128
+ ],
129
+ },
130
+ },
131
+ },
132
+ }
133
+
134
+ return run(config).then((result) => {
135
+ expect(result.css).toMatchFormattedCss(
136
+ css`
137
+ ${defaults}
138
+
139
+ .prose {
140
+ color: var(--tw-prose-body);
141
+ max-width: 65ch;
142
+ }
143
+ .prose :where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
144
+ color: var(--tw-prose-lead);
145
+ }
146
+ .prose :where(strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
147
+ color: var(--tw-prose-bold);
148
+ font-weight: 600;
149
+ }
150
+ .prose :where(ol[type='A']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
151
+ list-style-type: upper-alpha;
152
+ }
153
+ .prose
154
+ :where(blockquote p:first-of-type):not(:where([class~='not-prose'], [class~='not-prose']
155
+ *))::before {
156
+ content: open-quote;
157
+ }
158
+ .prose
159
+ :where(blockquote p:last-of-type):not(:where([class~='not-prose'], [class~='not-prose']
160
+ *))::after {
161
+ content: close-quote;
162
+ }
163
+ .prose :where(h4 strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
164
+ font-weight: 700;
165
+ }
166
+ .prose :where(figure > *):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
167
+ margin: 0;
168
+ }
169
+ .prose :where(ol > li):not(:where([class~='not-prose'], [class~='not-prose'] *))::marker {
170
+ font-weight: 400;
171
+ color: var(--tw-prose-counters);
172
+ }
173
+ .prose
174
+ :where(.prose > ul > li p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
175
+ margin-top: 16px;
176
+ margin-bottom: 16px;
177
+ }
178
+ .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *))::before {
179
+ content: '&#96;';
180
+ }
181
+ .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *))::after {
182
+ content: '&#96;';
183
+ }
184
+ `
185
+ )
186
+ })
187
+ })
188
+
189
+ test('variants', async () => {
190
+ let config = {
191
+ content: [{ raw: html`<div class="sm:prose hover:prose-lg lg:prose-lg"></div>` }],
192
+ theme: {
193
+ typography: {
194
+ DEFAULT: {
195
+ css: [
196
+ {
197
+ color: 'red',
198
+ p: {
199
+ color: 'lime',
200
+ },
201
+ '> ul > li': {
202
+ color: 'purple',
203
+ },
204
+ },
205
+ ],
206
+ },
207
+ lg: {
208
+ css: {
209
+ color: 'green',
210
+ p: {
211
+ color: 'tomato',
212
+ },
213
+ '> ul > li': {
214
+ color: 'blue',
215
+ },
216
+ },
217
+ },
218
+ xl: {
219
+ css: {
220
+ color: 'yellow',
221
+ '> ul > li': {
222
+ color: 'hotpink',
223
+ },
224
+ },
225
+ },
226
+ },
227
+ },
228
+ }
229
+
230
+ return run(config).then((result) => {
231
+ expect(result.css).toMatchFormattedCss(
232
+ css`
233
+ ${defaults}
234
+
235
+ .hover\:prose-lg:hover {
236
+ color: green;
237
+ }
238
+ .hover\:prose-lg:hover :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
239
+ color: tomato;
240
+ }
241
+ .hover\:prose-lg:hover
242
+ :where(.hover\:prose-lg:hover
243
+ > ul
244
+ > li):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
245
+ color: blue;
246
+ }
247
+ @media (min-width: 640px) {
248
+ .sm\:prose {
249
+ color: red;
250
+ }
251
+ .sm\:prose :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
252
+ color: lime;
253
+ }
254
+ .sm\:prose
255
+ :where(.sm\:prose > ul > li):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
256
+ color: purple;
257
+ }
258
+ }
259
+ @media (min-width: 1024px) {
260
+ .lg\:prose-lg {
261
+ color: green;
262
+ }
263
+ .lg\:prose-lg :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
264
+ color: tomato;
265
+ }
266
+ .lg\:prose-lg
267
+ :where(.lg\:prose-lg > ul > li):not(:where([class~='not-prose'], [class~='not-prose']
268
+ *)) {
269
+ color: blue;
270
+ }
271
+ }
272
+ `
273
+ )
274
+ })
275
+ })
276
+
277
+ test('modifiers', async () => {
278
+ let config = {
279
+ content: [{ raw: html`<div class="prose prose-lg"></div>` }],
280
+ theme: {
281
+ typography: {
282
+ DEFAULT: {
283
+ css: [
284
+ {
285
+ color: 'var(--tw-prose-body)',
286
+ maxWidth: '65ch',
287
+ '[class~="lead"]': {
288
+ color: 'var(--tw-prose-lead)',
289
+ },
290
+ strong: {
291
+ color: 'var(--tw-prose-bold)',
292
+ fontWeight: '600',
293
+ },
294
+ 'ol[type="A"]': {
295
+ listStyleType: 'upper-alpha',
296
+ },
297
+ 'blockquote p:first-of-type::before': {
298
+ content: 'open-quote',
299
+ },
300
+ 'blockquote p:last-of-type::after': {
301
+ content: 'close-quote',
302
+ },
303
+ 'h4 strong': {
304
+ fontWeight: '700',
305
+ },
306
+ 'figure > *': {
307
+ margin: 0,
308
+ },
309
+ 'ol > li::marker': {
310
+ fontWeight: '400',
311
+ color: 'var(--tw-prose-counters)',
312
+ },
313
+ 'code::before': {
314
+ content: '"&#96;"',
315
+ },
316
+ 'code::after': {
317
+ content: '"&#96;"',
318
+ },
319
+ },
320
+ ],
321
+ },
322
+ lg: {
323
+ css: [
324
+ {
325
+ fontSize: '18px',
326
+ lineHeight: '1.75',
327
+ p: {
328
+ marginTop: '24px',
329
+ marginBottom: '24px',
330
+ },
331
+ '[class~="lead"]': {
332
+ fontSize: '22px',
333
+ },
334
+ blockquote: {
335
+ marginTop: '40px',
336
+ marginBottom: '40px',
337
+ },
338
+ '> ul > li': {
339
+ paddingLeft: '12px',
340
+ },
341
+ h1: {
342
+ fontSize: '48px',
343
+ marginTop: '0',
344
+ marginBottom: '40px',
345
+ },
346
+ h2: {
347
+ fontSize: '30px',
348
+ marginTop: '56px',
349
+ marginBottom: '32px',
350
+ },
351
+ h3: {
352
+ fontSize: '24px',
353
+ marginTop: '40px',
354
+ marginBottom: '16px',
355
+ },
356
+ },
357
+ ],
358
+ },
359
+ },
360
+ },
361
+ }
362
+
363
+ return run(config).then((result) => {
364
+ expect(result.css).toMatchFormattedCss(
365
+ css`
366
+ ${defaults}
367
+
368
+ .prose {
369
+ color: var(--tw-prose-body);
370
+ max-width: 65ch;
371
+ }
372
+ .prose :where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
373
+ color: var(--tw-prose-lead);
374
+ }
375
+ .prose :where(strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
376
+ color: var(--tw-prose-bold);
377
+ font-weight: 600;
378
+ }
379
+ .prose :where(ol[type='A']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
380
+ list-style-type: upper-alpha;
381
+ }
382
+ .prose
383
+ :where(blockquote p:first-of-type):not(:where([class~='not-prose'], [class~='not-prose']
384
+ *))::before {
385
+ content: open-quote;
386
+ }
387
+ .prose
388
+ :where(blockquote p:last-of-type):not(:where([class~='not-prose'], [class~='not-prose']
389
+ *))::after {
390
+ content: close-quote;
391
+ }
392
+ .prose :where(h4 strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
393
+ font-weight: 700;
394
+ }
395
+ .prose :where(figure > *):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
396
+ margin: 0;
397
+ }
398
+ .prose :where(ol > li):not(:where([class~='not-prose'], [class~='not-prose'] *))::marker {
399
+ font-weight: 400;
400
+ color: var(--tw-prose-counters);
401
+ }
402
+ .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *))::before {
403
+ content: '&#96;';
404
+ }
405
+ .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *))::after {
406
+ content: '&#96;';
407
+ }
408
+ .prose-lg {
409
+ font-size: 18px;
410
+ line-height: 1.75;
411
+ }
412
+ .prose-lg :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
413
+ margin-top: 24px;
414
+ margin-bottom: 24px;
415
+ }
416
+ .prose-lg
417
+ :where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
418
+ font-size: 22px;
419
+ }
420
+ .prose-lg :where(blockquote):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
421
+ margin-top: 40px;
422
+ margin-bottom: 40px;
423
+ }
424
+ .prose-lg
425
+ :where(.prose-lg > ul > li):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
426
+ padding-left: 12px;
427
+ }
428
+ .prose-lg :where(h1):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
429
+ font-size: 48px;
430
+ margin-top: 0;
431
+ margin-bottom: 40px;
432
+ }
433
+ .prose-lg :where(h2):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
434
+ font-size: 30px;
435
+ margin-top: 56px;
436
+ margin-bottom: 32px;
437
+ }
438
+ .prose-lg :where(h3):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
439
+ font-size: 24px;
440
+ margin-top: 40px;
441
+ margin-bottom: 16px;
442
+ }
443
+ `
444
+ )
445
+ })
446
+ })
447
+
448
+ test('legacy target', async () => {
449
+ let config = {
450
+ plugins: [typographyPlugin({ target: 'legacy' })],
451
+ content: [
452
+ { raw: html`<div class="prose prose-h1:text-center prose-headings:text-ellipsis"></div>` },
453
+ ],
454
+ theme: {
455
+ typography: {
456
+ DEFAULT: {
457
+ css: [
458
+ {
459
+ color: 'var(--tw-prose-body)',
460
+ maxWidth: '65ch',
461
+ '[class~="lead"]': {
462
+ color: 'var(--tw-prose-lead)',
463
+ },
464
+ strong: {
465
+ color: 'var(--tw-prose-bold)',
466
+ fontWeight: '600',
467
+ },
468
+ 'ol[type="A"]': {
469
+ listStyleType: 'upper-alpha',
470
+ },
471
+ 'blockquote p:first-of-type::before': {
472
+ content: 'open-quote',
473
+ },
474
+ 'blockquote p:last-of-type::after': {
475
+ content: 'close-quote',
476
+ },
477
+ 'h4 strong': {
478
+ fontWeight: '700',
479
+ },
480
+ 'figure > *': {
481
+ margin: 0,
482
+ },
483
+ 'ol > li::marker': {
484
+ fontWeight: '400',
485
+ color: 'var(--tw-prose-counters)',
486
+ },
487
+ 'code::before': {
488
+ content: '"&#96;"',
489
+ },
490
+ 'code::after': {
491
+ content: '"&#96;"',
492
+ },
493
+ },
494
+ ],
495
+ },
496
+ },
497
+ },
498
+ }
499
+
500
+ return run(config).then((result) => {
501
+ expect(result.css).toMatchFormattedCss(
502
+ css`
503
+ ${defaults}
504
+
505
+ .prose {
506
+ color: var(--tw-prose-body);
507
+ max-width: 65ch;
508
+ }
509
+ .prose [class~='lead'] {
510
+ color: var(--tw-prose-lead);
511
+ }
512
+ .prose strong {
513
+ color: var(--tw-prose-bold);
514
+ font-weight: 600;
515
+ }
516
+ .prose ol[type='A'] {
517
+ list-style-type: upper-alpha;
518
+ }
519
+ .prose blockquote p:first-of-type::before {
520
+ content: open-quote;
521
+ }
522
+ .prose blockquote p:last-of-type::after {
523
+ content: close-quote;
524
+ }
525
+ .prose h4 strong {
526
+ font-weight: 700;
527
+ }
528
+ .prose figure > * {
529
+ margin: 0;
530
+ }
531
+ .prose ol > li::marker {
532
+ font-weight: 400;
533
+ color: var(--tw-prose-counters);
534
+ }
535
+ .prose code::before {
536
+ content: '&#96;';
537
+ }
538
+ .prose code::after {
539
+ content: '&#96;';
540
+ }
541
+ .prose-headings\:text-ellipsis h1 {
542
+ text-overflow: ellipsis;
543
+ }
544
+ .prose-headings\:text-ellipsis h2 {
545
+ text-overflow: ellipsis;
546
+ }
547
+ .prose-headings\:text-ellipsis h3 {
548
+ text-overflow: ellipsis;
549
+ }
550
+ .prose-headings\:text-ellipsis h4 {
551
+ text-overflow: ellipsis;
552
+ }
553
+ .prose-headings\:text-ellipsis h5 {
554
+ text-overflow: ellipsis;
555
+ }
556
+ .prose-headings\:text-ellipsis h6 {
557
+ text-overflow: ellipsis;
558
+ }
559
+ .prose-headings\:text-ellipsis th {
560
+ text-overflow: ellipsis;
561
+ }
562
+ .prose-h1\:text-center h1 {
563
+ text-align: center;
564
+ }
565
+ `
566
+ )
567
+ })
568
+ })
569
+
570
+ test('custom class name', async () => {
571
+ let config = {
572
+ plugins: [typographyPlugin({ className: 'markdown' })],
573
+ content: [{ raw: html`<div class="markdown"></div>` }],
574
+ theme: {
575
+ typography: {
576
+ DEFAULT: {
577
+ css: [
578
+ {
579
+ color: 'var(--tw-prose-body)',
580
+ maxWidth: '65ch',
581
+ '[class~="lead"]': {
582
+ color: 'var(--tw-prose-lead)',
583
+ },
584
+ strong: {
585
+ color: 'var(--tw-prose-bold)',
586
+ fontWeight: '600',
587
+ },
588
+ 'ol[type="A"]': {
589
+ listStyleType: 'upper-alpha',
590
+ },
591
+ 'blockquote p:first-of-type::before': {
592
+ content: 'open-quote',
593
+ },
594
+ 'blockquote p:last-of-type::after': {
595
+ content: 'close-quote',
596
+ },
597
+ 'h4 strong': {
598
+ fontWeight: '700',
599
+ },
600
+ 'figure > *': {
601
+ margin: 0,
602
+ },
603
+ 'ol > li::marker': {
604
+ fontWeight: '400',
605
+ color: 'var(--tw-prose-counters)',
606
+ },
607
+ 'code::before': {
608
+ content: '"&#96;"',
609
+ },
610
+ 'code::after': {
611
+ content: '"&#96;"',
612
+ },
613
+ },
614
+ ],
615
+ },
616
+ },
617
+ },
618
+ }
619
+
620
+ return run(config).then((result) => {
621
+ expect(result.css).toMatchFormattedCss(
622
+ css`
623
+ ${defaults}
624
+
625
+ .markdown {
626
+ color: var(--tw-prose-body);
627
+ max-width: 65ch;
628
+ }
629
+ .markdown
630
+ :where([class~='lead']):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
631
+ color: var(--tw-prose-lead);
632
+ }
633
+ .markdown :where(strong):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
634
+ color: var(--tw-prose-bold);
635
+ font-weight: 600;
636
+ }
637
+ .markdown
638
+ :where(ol[type='A']):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
639
+ list-style-type: upper-alpha;
640
+ }
641
+ .markdown
642
+ :where(blockquote
643
+ p:first-of-type):not(:where([class~='not-markdown'], [class~='not-markdown']
644
+ *))::before {
645
+ content: open-quote;
646
+ }
647
+ .markdown
648
+ :where(blockquote
649
+ p:last-of-type):not(:where([class~='not-markdown'], [class~='not-markdown'] *))::after {
650
+ content: close-quote;
651
+ }
652
+ .markdown
653
+ :where(h4 strong):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
654
+ font-weight: 700;
655
+ }
656
+ .markdown
657
+ :where(figure > *):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
658
+ margin: 0;
659
+ }
660
+ .markdown
661
+ :where(ol > li):not(:where([class~='not-markdown'], [class~='not-markdown'] *))::marker {
662
+ font-weight: 400;
663
+ color: var(--tw-prose-counters);
664
+ }
665
+ .markdown
666
+ :where(code):not(:where([class~='not-markdown'], [class~='not-markdown'] *))::before {
667
+ content: '&#96;';
668
+ }
669
+ .markdown
670
+ :where(code):not(:where([class~='not-markdown'], [class~='not-markdown'] *))::after {
671
+ content: '&#96;';
672
+ }
673
+ `
674
+ )
675
+ })
676
+ })
677
+
678
+ test('element variants', async () => {
679
+ let config = {
680
+ content: [
681
+ {
682
+ raw: html`<div
683
+ class="
684
+ prose
685
+ prose-headings:underline
686
+ prose-lead:italic
687
+ prose-h1:text-3xl
688
+ prose-h2:text-2xl
689
+ prose-h3:text-xl
690
+ prose-h4:text-lg
691
+ prose-p:text-gray-700
692
+ prose-a:font-bold
693
+ prose-blockquote:italic
694
+ prose-figure:mx-auto
695
+ prose-figcaption:opacity-75
696
+ prose-strong:font-medium
697
+ prose-em:italic
698
+ prose-kbd:border-b-2
699
+ prose-code:font-mono
700
+ prose-pre:font-mono
701
+ prose-ol:pl-6
702
+ prose-ul:pl-8
703
+ prose-li:my-4
704
+ prose-dl:pl-6
705
+ prose-dt:pl-8
706
+ prose-dd:my-4
707
+ prose-table:my-8
708
+ prose-thead:border-red-300
709
+ prose-tr:border-red-200
710
+ prose-th:text-left
711
+ prose-td:align-center
712
+ prose-img:rounded-lg
713
+ prose-picture:my-8
714
+ prose-video:my-12
715
+ prose-hr:border-t-2
716
+ "
717
+ ></div>`,
718
+ },
719
+ ],
720
+ theme: {
721
+ typography: {
722
+ DEFAULT: {
723
+ css: [
724
+ {
725
+ color: 'var(--tw-prose-body)',
726
+ '[class~="lead"]': {
727
+ color: 'var(--tw-prose-lead)',
728
+ },
729
+ strong: {
730
+ color: 'var(--tw-prose-bold)',
731
+ fontWeight: '600',
732
+ },
733
+ 'h4 strong': {
734
+ fontWeight: '700',
735
+ },
736
+ },
737
+ ],
738
+ },
739
+ },
740
+ },
741
+ }
742
+ return run(config).then((result) => {
743
+ expect(result.css).toMatchFormattedCss(
744
+ css`
745
+ ${defaults}
746
+
747
+ .prose {
748
+ color: var(--tw-prose-body);
749
+ }
750
+ .prose :where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
751
+ color: var(--tw-prose-lead);
752
+ }
753
+ .prose :where(strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
754
+ color: var(--tw-prose-bold);
755
+ font-weight: 600;
756
+ }
757
+ .prose :where(h4 strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
758
+ font-weight: 700;
759
+ }
760
+ .prose-headings\:underline
761
+ :is(:where(h1, h2, h3, h4, h5, h6, th):not(:where([class~='not-prose'], [class~='not-prose']
762
+ *))) {
763
+ text-decoration-line: underline;
764
+ }
765
+ .prose-h1\:text-3xl
766
+ :is(:where(h1):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
767
+ font-size: 1.875rem;
768
+ line-height: 2.25rem;
769
+ }
770
+ .prose-h2\:text-2xl
771
+ :is(:where(h2):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
772
+ font-size: 1.5rem;
773
+ line-height: 2rem;
774
+ }
775
+ .prose-h3\:text-xl
776
+ :is(:where(h3):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
777
+ font-size: 1.25rem;
778
+ line-height: 1.75rem;
779
+ }
780
+ .prose-h4\:text-lg
781
+ :is(:where(h4):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
782
+ font-size: 1.125rem;
783
+ line-height: 1.75rem;
784
+ }
785
+ .prose-p\:text-gray-700
786
+ :is(:where(p):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
787
+ --tw-text-opacity: 1;
788
+ color: rgb(55 65 81 / var(--tw-text-opacity));
789
+ }
790
+ .prose-a\:font-bold
791
+ :is(:where(a):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
792
+ font-weight: 700;
793
+ }
794
+ .prose-blockquote\:italic
795
+ :is(:where(blockquote):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
796
+ font-style: italic;
797
+ }
798
+ .prose-figure\:mx-auto
799
+ :is(:where(figure):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
800
+ margin-left: auto;
801
+ margin-right: auto;
802
+ }
803
+ .prose-figcaption\:opacity-75
804
+ :is(:where(figcaption):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
805
+ opacity: 0.75;
806
+ }
807
+ .prose-strong\:font-medium
808
+ :is(:where(strong):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
809
+ font-weight: 500;
810
+ }
811
+ .prose-em\:italic
812
+ :is(:where(em):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
813
+ font-style: italic;
814
+ }
815
+ .prose-kbd\:border-b-2
816
+ :is(:where(kbd):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
817
+ border-bottom-width: 2px;
818
+ }
819
+ .prose-code\:font-mono
820
+ :is(:where(code):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
821
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
822
+ 'Courier New', monospace;
823
+ }
824
+ .prose-pre\:font-mono
825
+ :is(:where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
826
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
827
+ 'Courier New', monospace;
828
+ }
829
+ .prose-ol\:pl-6 :is(:where(ol):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
830
+ padding-left: 1.5rem;
831
+ }
832
+ .prose-ul\:pl-8 :is(:where(ul):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
833
+ padding-left: 2rem;
834
+ }
835
+ .prose-li\:my-4 :is(:where(li):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
836
+ margin-top: 1rem;
837
+ margin-bottom: 1rem;
838
+ }
839
+ .prose-dl\:pl-6 :is(:where(dl):not(:where([class~="not-prose"], [class~="not-prose"] *))) {
840
+ padding-left: 1.5rem;
841
+ }
842
+ .prose-dt\:pl-8 :is(:where(dt):not(:where([class~="not-prose"], [class~="not-prose"] *))) {
843
+ padding-left: 2rem;
844
+ }
845
+ .prose-dd\:my-4 :is(:where(dd):not(:where([class~="not-prose"], [class~="not-prose"] *))) {
846
+ margin-top: 1rem;
847
+ margin-bottom: 1rem;
848
+ }
849
+ .prose-table\:my-8
850
+ :is(:where(table):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
851
+ margin-top: 2rem;
852
+ margin-bottom: 2rem;
853
+ }
854
+ .prose-thead\:border-red-300
855
+ :is(:where(thead):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
856
+ --tw-border-opacity: 1;
857
+ border-color: rgb(252 165 165 / var(--tw-border-opacity));
858
+ }
859
+ .prose-tr\:border-red-200
860
+ :is(:where(tr):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
861
+ --tw-border-opacity: 1;
862
+ border-color: rgb(254 202 202 / var(--tw-border-opacity));
863
+ }
864
+ .prose-th\:text-left
865
+ :is(:where(th):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
866
+ text-align: left;
867
+ }
868
+ .prose-img\:rounded-lg
869
+ :is(:where(img):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
870
+ border-radius: 0.5rem;
871
+ }
872
+ .prose-picture\:my-8
873
+ :is(:where(picture):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
874
+ margin-top: 2rem;
875
+ margin-bottom: 2rem;
876
+ }
877
+ .prose-video\:my-12
878
+ :is(:where(video):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
879
+ margin-top: 3rem;
880
+ margin-bottom: 3rem;
881
+ }
882
+ .prose-hr\:border-t-2
883
+ :is(:where(hr):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
884
+ border-top-width: 2px;
885
+ }
886
+ .prose-lead\:italic
887
+ :is(:where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
888
+ font-style: italic;
889
+ }
890
+ `
891
+ )
892
+ })
893
+ })
894
+
895
+ test('element variants with custom class name', async () => {
896
+ let config = {
897
+ plugins: [typographyPlugin({ className: 'markdown' })],
898
+ content: [
899
+ {
900
+ raw: html`<div
901
+ class="
902
+ markdown
903
+ markdown-headings:underline
904
+ markdown-lead:italic
905
+ markdown-h1:text-3xl
906
+ markdown-h2:text-2xl
907
+ markdown-h3:text-xl
908
+ markdown-h4:text-lg
909
+ markdown-p:text-gray-700
910
+ markdown-a:font-bold
911
+ markdown-blockquote:italic
912
+ markdown-figure:mx-auto
913
+ markdown-figcaption:opacity-75
914
+ markdown-strong:font-medium
915
+ markdown-em:italic
916
+ markdown-kbd:border-b-2
917
+ markdown-code:font-mono
918
+ markdown-pre:font-mono
919
+ markdown-ol:pl-6
920
+ markdown-ul:pl-8
921
+ markdown-li:my-4
922
+ markdown-table:my-8
923
+ markdown-thead:border-red-300
924
+ markdown-tr:border-red-200
925
+ markdown-th:text-left
926
+ markdown-td:align-center
927
+ markdown-img:rounded-lg
928
+ markdown-video:my-12
929
+ markdown-hr:border-t-2
930
+ "
931
+ ></div>`,
932
+ },
933
+ ],
934
+ theme: {
935
+ typography: {
936
+ DEFAULT: {
937
+ css: [
938
+ {
939
+ color: 'var(--tw-prose-body)',
940
+ '[class~="lead"]': {
941
+ color: 'var(--tw-prose-lead)',
942
+ },
943
+ strong: {
944
+ color: 'var(--tw-prose-bold)',
945
+ fontWeight: '600',
946
+ },
947
+ 'h4 strong': {
948
+ fontWeight: '700',
949
+ },
950
+ },
951
+ ],
952
+ },
953
+ },
954
+ },
955
+ }
956
+ return run(config).then((result) => {
957
+ expect(result.css).toMatchFormattedCss(
958
+ css`
959
+ ${defaults}
960
+
961
+ .markdown {
962
+ color: var(--tw-prose-body);
963
+ }
964
+ .markdown
965
+ :where([class~='lead']):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
966
+ color: var(--tw-prose-lead);
967
+ }
968
+ .markdown :where(strong):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
969
+ color: var(--tw-prose-bold);
970
+ font-weight: 600;
971
+ }
972
+ .markdown
973
+ :where(h4 strong):not(:where([class~='not-markdown'], [class~='not-markdown'] *)) {
974
+ font-weight: 700;
975
+ }
976
+ .markdown-headings\:underline
977
+ :is(:where(h1, h2, h3, h4, h5, h6, th):not(:where([class~='not-markdown'], [class~='not-markdown']
978
+ *))) {
979
+ text-decoration-line: underline;
980
+ }
981
+ .markdown-h1\:text-3xl
982
+ :is(:where(h1):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
983
+ font-size: 1.875rem;
984
+ line-height: 2.25rem;
985
+ }
986
+ .markdown-h2\:text-2xl
987
+ :is(:where(h2):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
988
+ font-size: 1.5rem;
989
+ line-height: 2rem;
990
+ }
991
+ .markdown-h3\:text-xl
992
+ :is(:where(h3):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
993
+ font-size: 1.25rem;
994
+ line-height: 1.75rem;
995
+ }
996
+ .markdown-h4\:text-lg
997
+ :is(:where(h4):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
998
+ font-size: 1.125rem;
999
+ line-height: 1.75rem;
1000
+ }
1001
+ .markdown-p\:text-gray-700
1002
+ :is(:where(p):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1003
+ --tw-text-opacity: 1;
1004
+ color: rgb(55 65 81 / var(--tw-text-opacity));
1005
+ }
1006
+ .markdown-a\:font-bold
1007
+ :is(:where(a):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1008
+ font-weight: 700;
1009
+ }
1010
+ .markdown-blockquote\:italic
1011
+ :is(:where(blockquote):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1012
+ font-style: italic;
1013
+ }
1014
+ .markdown-figure\:mx-auto
1015
+ :is(:where(figure):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1016
+ margin-left: auto;
1017
+ margin-right: auto;
1018
+ }
1019
+ .markdown-figcaption\:opacity-75
1020
+ :is(:where(figcaption):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1021
+ opacity: 0.75;
1022
+ }
1023
+ .markdown-strong\:font-medium
1024
+ :is(:where(strong):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1025
+ font-weight: 500;
1026
+ }
1027
+ .markdown-em\:italic
1028
+ :is(:where(em):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1029
+ font-style: italic;
1030
+ }
1031
+ .markdown-kbd\:border-b-2
1032
+ :is(:where(kbd):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1033
+ border-bottom-width: 2px;
1034
+ }
1035
+ .markdown-code\:font-mono
1036
+ :is(:where(code):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1037
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
1038
+ 'Courier New', monospace;
1039
+ }
1040
+ .markdown-pre\:font-mono
1041
+ :is(:where(pre):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1042
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
1043
+ 'Courier New', monospace;
1044
+ }
1045
+ .markdown-ol\:pl-6
1046
+ :is(:where(ol):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1047
+ padding-left: 1.5rem;
1048
+ }
1049
+ .markdown-ul\:pl-8
1050
+ :is(:where(ul):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1051
+ padding-left: 2rem;
1052
+ }
1053
+ .markdown-li\:my-4
1054
+ :is(:where(li):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1055
+ margin-top: 1rem;
1056
+ margin-bottom: 1rem;
1057
+ }
1058
+ .markdown-table\:my-8
1059
+ :is(:where(table):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1060
+ margin-top: 2rem;
1061
+ margin-bottom: 2rem;
1062
+ }
1063
+ .markdown-thead\:border-red-300
1064
+ :is(:where(thead):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1065
+ --tw-border-opacity: 1;
1066
+ border-color: rgb(252 165 165 / var(--tw-border-opacity));
1067
+ }
1068
+ .markdown-tr\:border-red-200
1069
+ :is(:where(tr):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1070
+ --tw-border-opacity: 1;
1071
+ border-color: rgb(254 202 202 / var(--tw-border-opacity));
1072
+ }
1073
+ .markdown-th\:text-left
1074
+ :is(:where(th):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1075
+ text-align: left;
1076
+ }
1077
+ .markdown-img\:rounded-lg
1078
+ :is(:where(img):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1079
+ border-radius: 0.5rem;
1080
+ }
1081
+ .markdown-video\:my-12
1082
+ :is(:where(video):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1083
+ margin-top: 3rem;
1084
+ margin-bottom: 3rem;
1085
+ }
1086
+ .markdown-hr\:border-t-2
1087
+ :is(:where(hr):not(:where([class~='not-markdown'], [class~='not-markdown'] *))) {
1088
+ border-top-width: 2px;
1089
+ }
1090
+ .markdown-lead\:italic
1091
+ :is(:where([class~='lead']):not(:where([class~='not-markdown'], [class~='not-markdown']
1092
+ *))) {
1093
+ font-style: italic;
1094
+ }
1095
+ `
1096
+ )
1097
+ })
1098
+ })
1099
+
1100
+ test('customizing defaults with multiple values does not result in invalid css', async () => {
1101
+ let config = {
1102
+ plugins: [typographyPlugin()],
1103
+ content: [
1104
+ {
1105
+ raw: html`<div class="prose"></div>`,
1106
+ },
1107
+ ],
1108
+ theme: {
1109
+ typography: {
1110
+ DEFAULT: {
1111
+ css: {
1112
+ textAlign: ['-webkit-match-parent', 'match-parent'],
1113
+ },
1114
+ },
1115
+ },
1116
+ },
1117
+ }
1118
+ return run(config).then((result) => {
1119
+ expect(result.css).toMatchFormattedCss(
1120
+ css`
1121
+ ${defaults}
1122
+
1123
+ .prose {
1124
+ text-align: -webkit-match-parent;
1125
+ text-align: match-parent;
1126
+ }
1127
+ `
1128
+ )
1129
+ })
1130
+ })
1131
+
1132
+ it('should be possible to use nested syntax (&) when extending the config', () => {
1133
+ let config = {
1134
+ plugins: [typographyPlugin()],
1135
+ content: [
1136
+ {
1137
+ raw: html`<div class="prose"></div>`,
1138
+ },
1139
+ ],
1140
+ theme: {
1141
+ extend: {
1142
+ typography: {
1143
+ DEFAULT: {
1144
+ css: {
1145
+ color: '#000',
1146
+ a: {
1147
+ color: '#888',
1148
+ '&:hover': {
1149
+ color: '#ff0000',
1150
+ },
1151
+ },
1152
+ },
1153
+ },
1154
+ },
1155
+ },
1156
+ },
1157
+ }
1158
+
1159
+ return run(config).then((result) => {
1160
+ expect(result.css).toIncludeCss(css`
1161
+ .prose {
1162
+ color: #000;
1163
+ max-width: 65ch;
1164
+ }
1165
+ `)
1166
+
1167
+ expect(result.css).toIncludeCss(css`
1168
+ .prose :where(a):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
1169
+ color: #888;
1170
+ text-decoration: underline;
1171
+ font-weight: 500;
1172
+ }
1173
+ `)
1174
+
1175
+ expect(result.css).toIncludeCss(css`
1176
+ .prose :where(a):not(:where([class~='not-prose'], [class~='not-prose'] *)):hover {
1177
+ color: #ff0000;
1178
+ }
1179
+ `)
1180
+ })
1181
+ })
1182
+
1183
+ it('should be possible to specify custom h5 and h6 styles', () => {
1184
+ let config = {
1185
+ plugins: [typographyPlugin()],
1186
+ content: [
1187
+ {
1188
+ raw: html`<div class="prose prose-h5:text-sm prose-h6:text-xl"></div>`,
1189
+ },
1190
+ ],
1191
+ }
1192
+
1193
+ return run(config).then((result) => {
1194
+ expect(result.css).toIncludeCss(css`
1195
+ .prose-h5\:text-sm :is(:where(h5):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
1196
+ font-size: 0.875rem;
1197
+ line-height: 1.25rem;
1198
+ }
1199
+ .prose-h6\:text-xl :is(:where(h6):not(:where([class~='not-prose'], [class~='not-prose'] *))) {
1200
+ font-size: 1.25rem;
1201
+ line-height: 1.75rem;
1202
+ }
1203
+ `)
1204
+ })
1205
+ })
1206
+
1207
+ it('should not break with multiple selectors with pseudo elements using variants', () => {
1208
+ let config = {
1209
+ darkMode: 'class',
1210
+ plugins: [typographyPlugin()],
1211
+ content: [
1212
+ {
1213
+ raw: html`<div class="dark:prose"></div>`,
1214
+ },
1215
+ ],
1216
+ theme: {
1217
+ typography: {
1218
+ DEFAULT: {
1219
+ css: {
1220
+ 'ol li::before, ul li::before': {
1221
+ color: 'red',
1222
+ },
1223
+ },
1224
+ },
1225
+ },
1226
+ },
1227
+ }
1228
+
1229
+ return run(config).then((result) => {
1230
+ expect(result.css).toIncludeCss(css`
1231
+ .dark
1232
+ .dark\:prose
1233
+ :where(ol li, ul li):not(:where([class~='not-prose'], [class~='not-prose'] *))::before {
1234
+ color: red;
1235
+ }
1236
+ `)
1237
+ })
1238
+ })
1239
+
1240
+ it('lifts all common, trailing pseudo elements when the same across all selectors', () => {
1241
+ let config = {
1242
+ darkMode: 'class',
1243
+ plugins: [typographyPlugin()],
1244
+ content: [
1245
+ {
1246
+ raw: html`<div class="prose dark:prose"></div>`,
1247
+ },
1248
+ ],
1249
+ theme: {
1250
+ typography: {
1251
+ DEFAULT: {
1252
+ css: {
1253
+ 'ol li::marker::before, ul li::marker::before': {
1254
+ color: 'red',
1255
+ },
1256
+ },
1257
+ },
1258
+ },
1259
+ },
1260
+ }
1261
+
1262
+ return run(config).then((result) => {
1263
+ expect(result.css).toIncludeCss(css`
1264
+ .prose
1265
+ :where(ol li, ul li):not(:where([class~='not-prose'], [class~='not-prose']
1266
+ *))::marker::before {
1267
+ color: red;
1268
+ }
1269
+ `)
1270
+
1271
+ // TODO: The output here is a bug in tailwindcss variant selector rewriting
1272
+ // IT should be ::marker::before
1273
+ expect(result.css).toIncludeCss(css`
1274
+ .dark
1275
+ .dark\:prose
1276
+ :where(ol li, ul li):not(:where([class~='not-prose'], [class~='not-prose']
1277
+ *))::before::marker {
1278
+ color: red;
1279
+ }
1280
+ `)
1281
+ })
1282
+ })
1283
+
1284
+ it('does not modify selectors with differing pseudo elements', () => {
1285
+ let config = {
1286
+ darkMode: 'class',
1287
+ plugins: [typographyPlugin()],
1288
+ content: [
1289
+ {
1290
+ raw: html`<div class="prose dark:prose"></div>`,
1291
+ },
1292
+ ],
1293
+ theme: {
1294
+ typography: {
1295
+ DEFAULT: {
1296
+ css: {
1297
+ 'ol li::before, ul li::after': {
1298
+ color: 'red',
1299
+ },
1300
+ },
1301
+ },
1302
+ },
1303
+ },
1304
+ }
1305
+
1306
+ return run(config).then((result) => {
1307
+ expect(result.css).toIncludeCss(css`
1308
+ .prose
1309
+ :where(ol li::before, ul li::after):not(:where([class~='not-prose'], [class~='not-prose']
1310
+ *)) {
1311
+ color: red;
1312
+ }
1313
+ `)
1314
+
1315
+ // TODO: The output here is a bug in tailwindcss variant selector rewriting
1316
+ expect(result.css).toIncludeCss(css`
1317
+ .dark
1318
+ .dark\:prose
1319
+ :where(ol li, ul li):not(:where([class~='not-prose'], [class~='not-prose'] *))::before,
1320
+ ::after {
1321
+ color: red;
1322
+ }
1323
+ `)
1324
+ })
1325
+ })
1326
+
1327
+ it('lifts only the common, trailing pseudo elements from selectors', () => {
1328
+ let config = {
1329
+ darkMode: 'class',
1330
+ plugins: [typographyPlugin()],
1331
+ content: [
1332
+ {
1333
+ raw: html`<div class="prose dark:prose"></div>`,
1334
+ },
1335
+ ],
1336
+ theme: {
1337
+ typography: {
1338
+ DEFAULT: {
1339
+ css: {
1340
+ 'ol li::scroll-thumb::before, ul li::scroll-track::before': {
1341
+ color: 'red',
1342
+ },
1343
+ },
1344
+ },
1345
+ },
1346
+ },
1347
+ }
1348
+
1349
+ return run(config).then((result) => {
1350
+ expect(result.css).toIncludeCss(css`
1351
+ .prose
1352
+ :where(ol li::scroll-thumb, ul
1353
+ li::scroll-track):not(:where([class~='not-prose'], [class~='not-prose'] *))::before {
1354
+ color: red;
1355
+ }
1356
+ `)
1357
+
1358
+ // TODO: The output here is a bug in tailwindcss variant selector rewriting
1359
+ expect(result.css).toIncludeCss(css`
1360
+ .dark
1361
+ .dark\:prose
1362
+ :where(ol li, ul li):not(:where([class~='not-prose'], [class~='not-prose']
1363
+ *))::scroll-thumb,
1364
+ ::scroll-track,
1365
+ ::before {
1366
+ color: red;
1367
+ }
1368
+ `)
1369
+ })
1370
+ })
1371
+
1372
+ it('ignores common non-trailing pseudo-elements in selectors', () => {
1373
+ let config = {
1374
+ darkMode: 'class',
1375
+ plugins: [typographyPlugin()],
1376
+ content: [
1377
+ {
1378
+ raw: html`<div class="prose dark:prose"></div>`,
1379
+ },
1380
+ ],
1381
+ theme: {
1382
+ typography: {
1383
+ DEFAULT: {
1384
+ css: {
1385
+ 'ol li::before::scroll-thumb, ul li::before::scroll-track': {
1386
+ color: 'red',
1387
+ },
1388
+ },
1389
+ },
1390
+ },
1391
+ },
1392
+ }
1393
+
1394
+ return run(config).then((result) => {
1395
+ expect(result.css).toIncludeCss(css`
1396
+ .prose
1397
+ :where(ol li::before::scroll-thumb, ul
1398
+ li::before::scroll-track):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
1399
+ color: red;
1400
+ }
1401
+ `)
1402
+
1403
+ // TODO: The output here is a bug in tailwindcss variant selector rewriting
1404
+ expect(result.css).toIncludeCss(css`
1405
+ .dark
1406
+ .dark\:prose
1407
+ :where(ol li::scroll-thumb, ul
1408
+ li::scroll-track):not(:where([class~='not-prose'], [class~='not-prose'] *))::before,
1409
+ ::before {
1410
+ color: red;
1411
+ }
1412
+ `)
1413
+ })
1414
+ })
1415
+
1416
+ test('lead styles are inserted after paragraph styles', async () => {
1417
+ let config = {
1418
+ content: [{ raw: html`<div class="prose"></div>` }],
1419
+ }
1420
+
1421
+ return run(config).then((result) => {
1422
+ expect(result.css).toIncludeCss(
1423
+ css`
1424
+ .prose {
1425
+ color: var(--tw-prose-body);
1426
+ max-width: 65ch;
1427
+ }
1428
+ .prose :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
1429
+ margin-top: 1.25em;
1430
+ margin-bottom: 1.25em;
1431
+ }
1432
+ .prose :where([class~='lead']):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
1433
+ color: var(--tw-prose-lead);
1434
+ font-size: 1.25em;
1435
+ line-height: 1.6;
1436
+ margin-top: 1.2em;
1437
+ margin-bottom: 1.2em;
1438
+ }
1439
+ `
1440
+ )
1441
+ })
1442
+ })