0
# Utilities and Helpers
1
2
UnoCSS Core provides a comprehensive utility library with functions for CSS processing, type manipulation, selector escaping, variant group handling, and development helpers.
3
4
## Array and Type Utilities
5
6
```typescript { .api }
7
function toArray<T>(value: T | T[] = []): T[];
8
function uniq<T>(value: T[]): T[];
9
function uniqueBy<T>(array: readonly T[], equalFn: (a: T, b: T) => boolean): T[];
10
function isString(s: any): s is string;
11
function notNull<T>(value: T | null | undefined): value is T;
12
function noop(): void;
13
```
14
15
**Basic type and array manipulation:**
16
- **toArray**: Converts single values or arrays to arrays
17
- **uniq**: Removes duplicate values from arrays
18
- **uniqueBy**: Removes duplicates using custom comparison function
19
- **isString**: Type guard for string values
20
- **notNull**: Type guard for non-null values
21
- **noop**: No-operation function
22
23
### Usage Examples
24
25
```typescript
26
import { toArray, uniq, uniqueBy, isString } from '@unocss/core';
27
28
// Convert to array
29
toArray('single') // ['single']
30
toArray(['already', 'array']) // ['already', 'array']
31
32
// Remove duplicates
33
uniq(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']
34
35
// Remove duplicates with custom comparison
36
const items = [{ id: 1, name: 'A' }, { id: 1, name: 'B' }, { id: 2, name: 'C' }];
37
uniqueBy(items, (a, b) => a.id === b.id) // [{ id: 1, name: 'A' }, { id: 2, name: 'C' }]
38
39
// Type checking
40
if (isString(value)) {
41
// TypeScript knows value is string here
42
console.log(value.toUpperCase());
43
}
44
```
45
46
## CSS Processing Utilities
47
48
```typescript { .api }
49
function normalizeCSSEntries(obj: string | CSSEntriesInput | CSSObjectInput): string | CSSEntries;
50
function normalizeCSSValues(obj: CSSValueInput | string | (CSSValueInput | string)[]): (string | CSSEntries)[];
51
function entriesToCss(arr?: CSSEntries): string;
52
function clearIdenticalEntries(entry: CSSEntries): CSSEntries;
53
54
const VirtualKey: string = '__virtual_key__';
55
```
56
57
**CSS data processing:**
58
- **normalizeCSSEntries**: Converts CSS objects/entries to normalized format
59
- **normalizeCSSValues**: Normalizes various CSS value input formats
60
- **entriesToCss**: Converts CSS entries to CSS string
61
- **clearIdenticalEntries**: Removes duplicate CSS properties
62
- **VirtualKey**: Special key for virtual CSS properties
63
64
### CSS Processing Examples
65
66
```typescript
67
import { normalizeCSSEntries, entriesToCss } from '@unocss/core';
68
69
// Normalize CSS input
70
const entries = normalizeCSSEntries({
71
color: 'red',
72
margin: '1rem',
73
padding: '0.5rem'
74
});
75
76
// Convert to CSS string
77
const css = entriesToCss([
78
['color', 'red'],
79
['margin', '1rem'],
80
['padding', '0.5rem']
81
]);
82
// Result: "color:red;margin:1rem;padding:0.5rem;"
83
```
84
85
## Object Manipulation Utilities
86
87
```typescript { .api }
88
function mergeDeep<T>(original: T, patch: DeepPartial<T>, mergeArray?: boolean): T;
89
function clone<T>(val: T): T;
90
function isObject(item: any): item is Record<string, any>;
91
```
92
93
**Deep object operations:**
94
- **mergeDeep**: Deep merges objects with optional array merging
95
- **clone**: Creates deep copy of values (objects, arrays, primitives)
96
- **isObject**: Type guard for plain objects
97
98
### Object Utility Examples
99
100
```typescript
101
import { mergeDeep, clone } from '@unocss/core';
102
103
// Deep merge objects
104
const original = { theme: { colors: { primary: 'blue' } } };
105
const patch = { theme: { colors: { secondary: 'red' } } };
106
const merged = mergeDeep(original, patch);
107
// Result: { theme: { colors: { primary: 'blue', secondary: 'red' } } }
108
109
// Clone objects
110
const original = { nested: { value: 42 } };
111
const cloned = clone(original);
112
cloned.nested.value = 100; // original.nested.value is still 42
113
```
114
115
## Selector Escaping
116
117
```typescript { .api }
118
function escapeSelector(str: string): string;
119
function escapeRegExp(string: string): string;
120
const e: typeof escapeSelector;
121
```
122
123
**CSS selector escaping:**
124
- **escapeSelector**: Escapes CSS selector strings according to CSS spec
125
- **escapeRegExp**: Escapes regex special characters
126
- **e**: Short alias for escapeSelector
127
128
### Escaping Examples
129
130
```typescript
131
import { escapeSelector, e } from '@unocss/core';
132
133
// Escape CSS selectors
134
escapeSelector('bg-red-500') // '.bg-red-500'
135
escapeSelector('w-1/2') // '.w-1\\/2'
136
escapeSelector('2xl:text-lg') // '.\\32 xl\\:text-lg'
137
138
// Short alias
139
e('hover:bg-blue') // '.hover\\:bg-blue'
140
```
141
142
## Rule and Shortcut Type Guards
143
144
```typescript { .api }
145
function isStaticRule(rule: Rule<any>): rule is StaticRule;
146
function isStaticShortcut(sc: Shortcut<any>): sc is StaticShortcut;
147
function isRawUtil(util: ParsedUtil | RawUtil | StringifiedUtil): util is RawUtil;
148
```
149
150
**Type discrimination:**
151
- **isStaticRule**: Checks if rule is static (string matcher)
152
- **isStaticShortcut**: Checks if shortcut is static
153
- **isRawUtil**: Checks if utility is raw CSS
154
155
## Variant Group Processing
156
157
```typescript { .api }
158
function parseVariantGroup(str: string | MagicString, separators?: string[], depth?: number): {
159
prefixes: string[];
160
hasChanged: boolean;
161
groupsByOffset: Map<number, VariantGroup>;
162
expanded: string;
163
};
164
165
function expandVariantGroup(str: string, separators?: string[], depth?: number): string;
166
function expandVariantGroup(str: MagicString, separators?: string[], depth?: number): MagicString;
167
168
function collapseVariantGroup(str: string, prefixes: string[]): string;
169
function makeRegexClassGroup(separators?: string[]): RegExp;
170
```
171
172
**Variant group manipulation:**
173
- **parseVariantGroup**: Parses variant group syntax with detailed information
174
- **expandVariantGroup**: Expands variant groups into individual classes
175
- **collapseVariantGroup**: Collapses classes back into variant groups
176
- **makeRegexClassGroup**: Creates regex for matching variant groups
177
178
### Variant Group Examples
179
180
```typescript
181
import { expandVariantGroup, collapseVariantGroup } from '@unocss/core';
182
183
// Expand variant groups
184
expandVariantGroup('hover:(bg-red text-white)')
185
// Result: 'hover:bg-red hover:text-white'
186
187
expandVariantGroup('md:(flex items-center) lg:(grid grid-cols-2)')
188
// Result: 'md:flex md:items-center lg:grid lg:grid-cols-2'
189
190
// Collapse back to groups
191
collapseVariantGroup('hover:bg-red hover:text-white', ['hover:'])
192
// Result: 'hover:(bg-red text-white)'
193
```
194
195
## Enhanced Data Structures
196
197
### CountableSet
198
199
```typescript { .api }
200
class CountableSet<K> extends Set<K> {
201
getCount(key: K): number;
202
setCount(key: K, count: number): this;
203
add(key: K): this;
204
delete(key: K): boolean;
205
clear(): void;
206
}
207
208
function isCountableSet<T = string>(value: any): value is CountableSet<T>;
209
```
210
211
Set that tracks occurrence frequency for each item.
212
213
### TwoKeyMap
214
215
```typescript { .api }
216
class TwoKeyMap<K1, K2, V> {
217
get(key1: K1, key2: K2): V | undefined;
218
getFallback(key1: K1, key2: K2, fallback: V): V;
219
set(key1: K1, key2: K2, value: V): this;
220
has(key1: K1, key2: K2): boolean;
221
delete(key1: K1, key2: K2): boolean;
222
deleteTop(key1: K1): boolean;
223
map<T>(fn: (v: V, k1: K1, k2: K2) => T): T[];
224
}
225
```
226
227
Two-level map for nested key-value storage.
228
229
### BetterMap
230
231
```typescript { .api }
232
class BetterMap<K, V> extends Map<K, V> {
233
getFallback(key: K, fallback: V): V;
234
map<R>(mapFn: (value: V, key: K) => R): R[];
235
flatMap<R extends readonly unknown[]>(mapFn: (value: V, key: K) => R): R[number][];
236
}
237
```
238
239
Enhanced Map with utility methods.
240
241
### Data Structure Examples
242
243
```typescript
244
import { CountableSet, TwoKeyMap, BetterMap } from '@unocss/core';
245
246
// CountableSet usage
247
const classes = new CountableSet(['flex', 'p-4', 'flex']);
248
classes.getCount('flex') // 2
249
classes.getCount('p-4') // 1
250
251
// TwoKeyMap usage
252
const cache = new TwoKeyMap<string, string, number>();
253
cache.set('theme', 'dark', 1);
254
cache.set('theme', 'light', 2);
255
cache.get('theme', 'dark') // 1
256
257
// BetterMap usage
258
const map = new BetterMap();
259
map.set('a', 1);
260
map.set('b', 2);
261
map.getFallback('c', 3) // Sets and returns 3
262
map.map((value, key) => `${key}:${value}`) // ['a:1', 'b:2', 'c:3']
263
```
264
265
## Layer Utilities
266
267
```typescript { .api }
268
function withLayer<T extends object>(layer: string, rules: Rule<T>[]): Rule<T>[];
269
```
270
271
Adds layer metadata to rules.
272
273
```typescript
274
import { withLayer } from '@unocss/core';
275
276
const componentRules = [
277
['btn', { padding: '0.5rem 1rem' }],
278
['card', { border: '1px solid #ccc' }]
279
];
280
281
const layeredRules = withLayer('components', componentRules);
282
// All rules now have layer: 'components' metadata
283
```
284
285
## Event System
286
287
```typescript { .api }
288
function createNanoEvents<Events extends EventsMap = DefaultEvents>(): Emitter<Events>;
289
290
interface Emitter<Events extends EventsMap = DefaultEvents> {
291
events: Partial<{ [E in keyof Events]: Events[E][] }>;
292
on<K extends keyof Events>(event: K, cb: Events[K]): Unsubscribe;
293
emit<K extends keyof Events>(event: K, ...args: Parameters<Events[K]>): void;
294
}
295
296
interface Unsubscribe {
297
(): void;
298
}
299
```
300
301
Lightweight event emitter for internal communication.
302
303
## Warning System
304
305
```typescript { .api }
306
function warnOnce(msg: string): void;
307
```
308
309
Warns once per unique message to avoid spam.
310
311
```typescript
312
import { warnOnce } from '@unocss/core';
313
314
// Only shows warning once even if called multiple times
315
warnOnce('Deprecated feature used');
316
warnOnce('Deprecated feature used'); // Silent
317
```
318
319
## Validator Utilities
320
321
```typescript { .api }
322
function isAttributifySelector(selector: string): boolean;
323
function isValidSelector(selector?: string): boolean;
324
function normalizeVariant(variant: Variant<any>): VariantObject<any>;
325
```
326
327
**Validation helpers:**
328
- **isAttributifySelector**: Checks if selector uses attributify syntax
329
- **isValidSelector**: Validates CSS selector format
330
- **normalizeVariant**: Converts variant functions to objects
331
332
### Validation Examples
333
334
```typescript
335
import { isAttributifySelector, isValidSelector } from '@unocss/core';
336
337
// Check selector types
338
isAttributifySelector('[bg-red~=""]') // true
339
isAttributifySelector('.bg-red') // false
340
341
// Validate selectors
342
isValidSelector('valid-class') // true
343
isValidSelector('') // false
344
isValidSelector('123invalid') // false
345
```