Skip to content

Commit 0c64c2f

Browse files
committed
chore: fix RTL preset replacements and improve checker accuracy
1 parent a330d04 commit 0c64c2f

2 files changed

Lines changed: 46 additions & 32 deletions

File tree

test/unit/uno-preset-rtl.spec.ts

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { afterEach, beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest'
22
import { presetRtl, resetRtlWarnings } from '../../uno-preset-rtl'
3-
import { createGenerator } from 'unocss'
3+
import { createGenerator, presetWind4 } from 'unocss'
44

55
describe('uno-preset-rtl', () => {
66
let warnSpy: MockInstance
@@ -16,43 +16,54 @@ describe('uno-preset-rtl', () => {
1616

1717
it('rtl rules replace css styles correctly', async () => {
1818
const uno = await createGenerator({
19-
presets: [presetRtl()],
19+
presets: [presetWind4(), presetRtl()],
2020
})
2121

2222
const { css } = await uno.generate(
23-
'left-0 right-0 pl-1 ml-1 pr-1 mr-1 text-left text-right border-l border-r rounded-l rounded-r',
23+
'left-0 right-0 pl-1 ml-1 pr-1 mr-1 text-left text-right border-l border-r rounded-l rounded-r sm:pl-2 hover:text-right position-left-4',
2424
)
2525

2626
expect(css).toMatchInlineSnapshot(`
27-
"/* layer: default */
28-
.pl-1{padding-inline-start:calc(var(--spacing) * 1);}
29-
.pr-1{padding-inline-end:calc(var(--spacing) * 1);}
30-
.ml-1{margin-inline-start:calc(var(--spacing) * 1);}
31-
.mr-1{margin-inline-end:calc(var(--spacing) * 1);}
32-
.left-0{inset-inline-start:calc(var(--spacing) * 0);}
33-
.right-0{inset-inline-end:calc(var(--spacing) * 0);}
34-
.text-left{text-align:start;}
35-
.text-right{text-align:end;}
36-
.border-l{border-inline-start-width:1px;}
37-
.border-r{border-inline-end-width:1px;}"
38-
`)
27+
"/* layer: theme */
28+
:root, :host { --spacing: 0.25rem; --font-sans: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; --font-mono: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; --default-font-family: var(--font-sans); --default-monoFont-family: var(--font-mono); }
29+
/* layer: base */
30+
*, ::after, ::before, ::backdrop, ::file-selector-button { box-sizing: border-box; margin: 0; padding: 0; border: 0 solid; } html, :host { line-height: 1.5; -webkit-text-size-adjust: 100%; tab-size: 4; font-family: var( --default-font-family, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji' ); font-feature-settings: var(--default-font-featureSettings, normal); font-variation-settings: var(--default-font-variationSettings, normal); -webkit-tap-highlight-color: transparent; } hr { height: 0; color: inherit; border-top-width: 1px; } abbr:where([title]) { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; } h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; } a { color: inherit; -webkit-text-decoration: inherit; text-decoration: inherit; } b, strong { font-weight: bolder; } code, kbd, samp, pre { font-family: var( --default-monoFont-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace ); font-feature-settings: var(--default-monoFont-featureSettings, normal); font-variation-settings: var(--default-monoFont-variationSettings, normal); font-size: 1em; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } table { text-indent: 0; border-color: inherit; border-collapse: collapse; } :-moz-focusring { outline: auto; } progress { vertical-align: baseline; } summary { display: list-item; } ol, ul, menu { list-style: none; } img, svg, video, canvas, audio, iframe, embed, object { display: block; vertical-align: middle; } img, video { max-width: 100%; height: auto; } button, input, select, optgroup, textarea, ::file-selector-button { font: inherit; font-feature-settings: inherit; font-variation-settings: inherit; letter-spacing: inherit; color: inherit; border-radius: 0; background-color: transparent; opacity: 1; } :where(select:is([multiple], [size])) optgroup { font-weight: bolder; } :where(select:is([multiple], [size])) optgroup option { padding-inline-start: 20px; } ::file-selector-button { margin-inline-end: 4px; } ::placeholder { opacity: 1; } @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { ::placeholder { color: color-mix(in oklab, currentcolor 50%, transparent); } } textarea { resize: vertical; } ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-date-and-time-value { min-height: 1lh; text-align: inherit; } ::-webkit-datetime-edit { display: inline-flex; } ::-webkit-datetime-edit-fields-wrapper { padding: 0; } ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { padding-block: 0; } ::-webkit-calendar-picker-indicator { line-height: 1; } :-moz-ui-invalid { box-shadow: none; } button, input:where([type='button'], [type='reset'], [type='submit']), ::file-selector-button { appearance: button; } ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; } [hidden]:where(:not([hidden~='until-found'])) { display: none !important; }
31+
/* layer: default */
32+
.text-left{text-align:left;}
33+
.text-right{text-align:right;}
34+
.hover\\:text-right:hover{text-align:right;}
35+
.pl-1{padding-inline-start:calc(var(--spacing) * 1);}
36+
.pr-1{padding-inline-end:calc(var(--spacing) * 1);}
37+
.ml-1{margin-inline-start:calc(var(--spacing) * 1);}
38+
.mr-1{margin-inline-end:calc(var(--spacing) * 1);}
39+
.left-0{inset-inline-start:calc(var(--spacing) * 0);}
40+
.position-left-4{inset-inline-start:calc(var(--spacing) * 4);}
41+
.right-0{inset-inline-end:calc(var(--spacing) * 0);}
42+
.rounded-l{border-end-start-radius:0.25rem;border-start-start-radius:0.25rem;}
43+
.rounded-r{border-start-end-radius:0.25rem;border-end-end-radius:0.25rem;}
44+
.border-l{border-inline-start-width:1px;}
45+
.border-r{border-inline-end-width:1px;}
46+
@media (min-width: 40rem){
47+
.sm\\:pl-2{padding-inline-start:calc(var(--spacing) * 2);}
48+
}"
49+
`)
3950

4051
const warnings = warnSpy.mock.calls.flat()
4152
expect(warnings).toMatchInlineSnapshot(`
42-
[
43-
"[RTL] Avoid using 'left-0'. Use 'inset-is-0' instead.",
44-
"[RTL] Avoid using 'right-0'. Use 'inset-ie-0' instead.",
45-
"[RTL] Avoid using 'pl-1'. Use 'ps-1' instead.",
46-
"[RTL] Avoid using 'ml-1'. Use 'ms-1' instead.",
47-
"[RTL] Avoid using 'pr-1'. Use 'pe-1' instead.",
48-
"[RTL] Avoid using 'mr-1'. Use 'me-1' instead.",
49-
"[RTL] Avoid using 'text-left'. Use 'text-start' instead.",
50-
"[RTL] Avoid using 'text-right'. Use 'text-end' instead.",
51-
"[RTL] Avoid using 'border-l'. Use 'border-is' instead.",
52-
"[RTL] Avoid using 'border-r'. Use 'border-ie' instead.",
53-
"[RTL] Avoid using 'rounded-l'. Use 'rounded-is' instead.",
54-
"[RTL] Avoid using 'rounded-r'. Use 'rounded-ie' instead.",
55-
]
56-
`)
53+
[
54+
"[RTL] Avoid using 'left-0'. Use 'inset-is-0' instead.",
55+
"[RTL] Avoid using 'right-0'. Use 'inset-ie-0' instead.",
56+
"[RTL] Avoid using 'pl-1'. Use 'ps-1' instead.",
57+
"[RTL] Avoid using 'ml-1'. Use 'ms-1' instead.",
58+
"[RTL] Avoid using 'pr-1'. Use 'pe-1' instead.",
59+
"[RTL] Avoid using 'mr-1'. Use 'me-1' instead.",
60+
"[RTL] Avoid using 'border-l'. Use 'border-is' instead.",
61+
"[RTL] Avoid using 'border-r'. Use 'border-ie' instead.",
62+
"[RTL] Avoid using 'rounded-l'. Use 'rounded-is' instead.",
63+
"[RTL] Avoid using 'rounded-r'. Use 'rounded-ie' instead.",
64+
"[RTL] Avoid using 'position-left-4'. Use 'inset-is-4' instead.",
65+
"[RTL] Avoid using 'sm:pl-2'. Use 'sm:ps-2' instead.",
66+
]
67+
`)
5768
})
5869
})

uno-preset-rtl.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,14 @@ export function presetRtl(checker?: CollectorChecker): Preset {
110110
const replacement = direction === 'left' ? 'inset-is' : 'inset-ie'
111111

112112
const fullClass = context.rawSelector || match
113-
const suggestedBase = match.replace(direction!, replacement)
113+
// match is 'left-4' or 'position-left-4'
114+
// replacement is 'inset-is' or 'inset-ie'
115+
// We want 'inset-is-4'
116+
const suggestedBase = `${replacement}-${size}`
114117
const suggestedClass = fullClass.replace(match, suggestedBase)
115118

116119
if (checker) {
117-
checker(`avoid using '${fullClass}'. Use '${suggestedClass}' instead.`, fullClass)
120+
checker(`avoid using '${fullClass}', use '${suggestedClass}' instead.`, fullClass)
118121
} else {
119122
warnOnce(
120123
`[RTL] Avoid using '${fullClass}'. Use '${suggestedClass}' instead.`,

0 commit comments

Comments
 (0)