0
# PostCSS Normalize Unicode
1
2
PostCSS Normalize Unicode is a PostCSS plugin that normalizes unicode-range descriptors in CSS @font-face rules. It intelligently converts ranges like `u+2b00-2bff` into more compact wildcard representations like `u+2b??` when the range covers complete hex digit positions, resulting in smaller CSS output while maintaining browser compatibility.
3
4
## Package Information
5
6
- **Package Name**: postcss-normalize-unicode
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install postcss-normalize-unicode`
10
11
## Core Imports
12
13
```javascript
14
const postcssNormalizeUnicode = require("postcss-normalize-unicode");
15
```
16
17
For ES modules:
18
19
```javascript
20
import postcssNormalizeUnicode from "postcss-normalize-unicode";
21
```
22
23
## Basic Usage
24
25
```javascript
26
const postcss = require("postcss");
27
const postcssNormalizeUnicode = require("postcss-normalize-unicode");
28
29
// Basic usage without options
30
const result = await postcss([
31
postcssNormalizeUnicode()
32
]).process(css, { from: undefined });
33
34
// With browserslist override
35
const result = await postcss([
36
postcssNormalizeUnicode({
37
overrideBrowserslist: ['defaults', 'not ie <=11']
38
})
39
]).process(css, { from: undefined });
40
```
41
42
**Input CSS:**
43
```css
44
@font-face {
45
font-family: test;
46
unicode-range: u+2b00-2bff;
47
}
48
```
49
50
**Output CSS:**
51
```css
52
@font-face {
53
font-family: test;
54
unicode-range: u+2b??;
55
}
56
```
57
58
## Architecture
59
60
The plugin operates by:
61
62
1. **Browser Detection**: Uses browserslist to determine target browsers and detect legacy IE/Edge compatibility requirements
63
2. **CSS Processing**: Walks through all `unicode-range` declarations in CSS during the `OnceExit` phase
64
3. **Value Parsing**: Uses postcss-value-parser to safely parse and transform unicode-range values
65
4. **Range Optimization**: Converts unicode ranges to wildcard patterns using the internal algorithm:
66
- Parses ranges like `u+2b00-2bff` into start/end bounds
67
- Compares hex digit positions from left to right
68
- Converts positions where start=0 and end=f to wildcard (?)
69
- Supports up to 5 wildcard characters maximum
70
- Falls back to original range if optimization isn't possible
71
5. **Legacy Support**: Automatically converts lowercase 'u' prefixes to uppercase 'U' for IE ≤11 and Edge ≤15
72
6. **Performance Optimization**: Implements caching to avoid re-processing identical values
73
74
## Capabilities
75
76
### Plugin Creator
77
78
Creates a PostCSS plugin instance for normalizing unicode-range descriptors.
79
80
```javascript { .api }
81
/**
82
* Creates a PostCSS plugin for normalizing unicode-range descriptors
83
* @param {Options} opts - Plugin configuration options
84
* @returns {import('postcss').Plugin} PostCSS plugin instance
85
*/
86
function postcssNormalizeUnicode(opts?: Options): import('postcss').Plugin;
87
```
88
89
### Unicode Range Normalization
90
91
The plugin automatically processes all `unicode-range` declarations and:
92
93
- Converts ranges like `u+2b00-2bff` to `u+2b??` when possible
94
- Converts ranges like `u+1e00-1eff` to `u+1e??` when possible
95
- Supports up to 5 wildcard characters (?) in range patterns
96
- Preserves ranges that cannot be optimized (e.g., `u+2125-2128`)
97
- Handles case normalization (converts to lowercase by default)
98
- Applies uppercase 'U' prefix for legacy browser compatibility when needed
99
100
### Browser Compatibility Handling
101
102
Automatically detects and handles browser-specific requirements:
103
104
- **Legacy browsers** (IE ≤11, Edge ≤15): Converts to uppercase 'U' prefix
105
- **Modern browsers**: Uses lowercase 'u' prefix for smaller output
106
- Uses browserslist configuration for automatic browser detection
107
108
## Configuration Options
109
110
```javascript { .api }
111
interface Options {
112
/** Override browserslist configuration for browser targeting */
113
overrideBrowserslist?: string | string[];
114
/** Custom usage statistics for browserslist */
115
stats?: object;
116
/** Custom path for browserslist config resolution */
117
path?: string;
118
/** Environment name for browserslist config */
119
env?: string;
120
}
121
```
122
123
### Configuration Properties
124
125
#### `overrideBrowserslist`
126
- **Type**: `string | string[]`
127
- **Optional**: Yes
128
- **Description**: Override the default browserslist configuration to target specific browsers
129
- **Example**: `['defaults', 'not ie <=11']` or `'IE 9'`
130
131
#### `stats`
132
- **Type**: `object`
133
- **Optional**: Yes
134
- **Description**: Custom usage statistics for browserslist browser selection
135
136
#### `path`
137
- **Type**: `string`
138
- **Optional**: Yes
139
- **Description**: Custom path for browserslist configuration file resolution
140
141
#### `env`
142
- **Type**: `string`
143
- **Optional**: Yes
144
- **Description**: Environment name to use from browserslist configuration (e.g., 'production', 'legacy')
145
146
## Usage Examples
147
148
### Basic Plugin Usage
149
150
```javascript
151
const postcss = require("postcss");
152
const postcssNormalizeUnicode = require("postcss-normalize-unicode");
153
154
const processor = postcss([postcssNormalizeUnicode()]);
155
156
const css = `
157
@font-face {
158
font-family: 'MyFont';
159
unicode-range: u+2b00-2bff, u+1e00-1eff;
160
}
161
`;
162
163
const result = await processor.process(css, { from: undefined });
164
console.log(result.css);
165
// Output: unicode-range: u+2b??, u+1e??;
166
```
167
168
### Legacy Browser Support
169
170
```javascript
171
// Force legacy browser compatibility
172
const processor = postcss([
173
postcssNormalizeUnicode({
174
overrideBrowserslist: 'IE 9'
175
})
176
]);
177
178
const result = await processor.process(css, { from: undefined });
179
// Output will use uppercase 'U+2b??' instead of 'u+2b??'
180
```
181
182
### Using Browserslist Environment
183
184
```javascript
185
// Use specific browserslist environment
186
const processor = postcss([
187
postcssNormalizeUnicode({
188
env: 'legacy'
189
})
190
]);
191
```
192
193
### Multiple Range Processing
194
195
```javascript
196
const postcss = require("postcss");
197
const postcssNormalizeUnicode = require("postcss-normalize-unicode");
198
199
const css = `
200
@font-face {
201
font-family: 'Icons';
202
unicode-range: u+2000-2fff, u+2120-212f, u+0-7f;
203
}
204
`;
205
206
const result = await postcss([postcssNormalizeUnicode()])
207
.process(css, { from: undefined });
208
209
console.log(result.css);
210
// Output:
211
// @font-face {
212
// font-family: 'Icons';
213
// unicode-range: u+2???, u+212?, u+0-7f;
214
// }
215
//
216
// Transformations applied:
217
// u+2000-2fff → u+2??? (4-digit range to 3 wildcards)
218
// u+2120-212f → u+212? (4-digit range to 1 wildcard)
219
// u+0-7f → remains unchanged (cannot be optimized)
220
```
221
222
## Browser Compatibility
223
224
- **Modern browsers**: Uses lowercase 'u' prefix (smaller output)
225
- **IE ≤11**: Requires uppercase 'U' prefix (automatically detected and applied)
226
- **Edge ≤15**: Requires uppercase 'U' prefix (automatically detected and applied)
227
- **Edge 16+**: Supports lowercase 'u' prefix
228
229
The plugin automatically detects browser requirements using browserslist configuration and applies the appropriate prefix casing.
230
231
## Plugin Properties
232
233
The plugin exposes a PostCSS compatibility marker to indicate it's a valid PostCSS plugin:
234
235
```javascript { .api }
236
// PostCSS plugin compatibility marker
237
postcssNormalizeUnicode.postcss = true;
238
```
239
240
## Error Handling
241
242
The plugin handles various edge cases gracefully:
243
244
- **Invalid ranges**: Preserves original values for ranges that don't follow expected patterns
245
- **Single values**: Passes through unicode ranges that aren't ranges (no dash)
246
- **Mismatched lengths**: Preserves ranges where start and end have different hex digit lengths
247
- **CSS variables and functions**: Passes through `var()`, `env()`, and other CSS functions unchanged
248
- **Unknown properties**: Only processes `unicode-range` declarations, ignores other properties
249
250
## Performance Features
251
252
- **Caching**: Results are cached during processing to avoid redundant transformations
253
- **Lazy evaluation**: Processing only occurs during PostCSS OnceExit phase for efficiency
254
- **Minimal parsing**: Uses postcss-value-parser for safe and efficient CSS value manipulation