@unocss/preset-icons 0.29.4 → 0.30.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/README.md +171 -0
- package/dist/index.cjs +34 -48
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +34 -48
- package/package.json +5 -11
- package/dist/fs.cjs +0 -27
- package/dist/fs.d.ts +0 -5
- package/dist/fs.mjs +0 -23
package/README.md
CHANGED
|
@@ -82,6 +82,177 @@ By default, this preset will choose the rendering modes automatically for each i
|
|
|
82
82
|
|
|
83
83
|
for example, `vscode-icons:file-type-light-db`, an icon with colors that will be rendered as a background image. Use `vscode-icons:file-type-light-db?bg` to render it as a mask image and bypass it's colors.
|
|
84
84
|
|
|
85
|
+
## Configuring collections and icons resolvers
|
|
86
|
+
|
|
87
|
+
You can provide collections via `@iconify-json/[the-collection-you-want]`, `@iconify/json` or using your custom ones using `collections` option on your `UnoCSS` configuration.
|
|
88
|
+
|
|
89
|
+
### Browser
|
|
90
|
+
|
|
91
|
+
To load `iconify` collections you should use `@iconify-json/[the-collection-you-want]` and not `@iconify/json` since the `json` file is huge.
|
|
92
|
+
You will need to provide the `iconify` collections using `dynamic imports`, for example, on playground you have these collections:
|
|
93
|
+
```ts
|
|
94
|
+
presetIcons({
|
|
95
|
+
collections: {
|
|
96
|
+
carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any),
|
|
97
|
+
mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default as any),
|
|
98
|
+
logos: () => import('@iconify-json/logos/icons.json').then(i => i.default as any),
|
|
99
|
+
twemoji: () => import('@iconify-json/twemoji/icons.json').then(i => i.default as any),
|
|
100
|
+
ri: () => import('@iconify-json/ri/icons.json').then(i => i.default as any),
|
|
101
|
+
tabler: () => import('@iconify-json/tabler/icons.json').then(i => i.default as any),
|
|
102
|
+
uim: () => import('@iconify-json/uim/icons.json').then(i => i.default as any)
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
You can also provide your own custom collections using [CustomIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L12) or [InlineCollection](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L61), for example using `InlineCollection`:
|
|
108
|
+
```ts
|
|
109
|
+
UnoCss({
|
|
110
|
+
presets: [
|
|
111
|
+
presetIcons({
|
|
112
|
+
collections: {
|
|
113
|
+
custom: {
|
|
114
|
+
circle: '<svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="50"></circle></svg>',
|
|
115
|
+
/* ... */
|
|
116
|
+
},
|
|
117
|
+
carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any),
|
|
118
|
+
/* ... */
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
]
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
and then, you can use it on your html: `<span class="i-custom:circle"></span>`
|
|
126
|
+
|
|
127
|
+
### Node.js
|
|
128
|
+
|
|
129
|
+
In `Node.js` the preset will search for the installed iconify dataset automatically and so you don't need to register the `iconify` collections.
|
|
130
|
+
|
|
131
|
+
You can also provide your own custom collections using also [CustomIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L12) or [InlineCollection](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L61).
|
|
132
|
+
|
|
133
|
+
Additionally, you can also use [FileSystemIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/loaders.ts#L9) to load your custom icons from your file system. You will need to install `@iconify/utils` package as `dev dependency`.
|
|
134
|
+
```ts
|
|
135
|
+
// vite.config.ts
|
|
136
|
+
import { promises as fs } from 'fs'
|
|
137
|
+
// loader helpers
|
|
138
|
+
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
|
|
139
|
+
|
|
140
|
+
UnoCss({
|
|
141
|
+
presets: [
|
|
142
|
+
presetIcons({
|
|
143
|
+
collections: {
|
|
144
|
+
// key as the collection name
|
|
145
|
+
'my-icons': {
|
|
146
|
+
'account': '<svg><!-- ... --></svg>',
|
|
147
|
+
// load your custom icon lazily
|
|
148
|
+
'settings': () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
|
|
149
|
+
/* ... */
|
|
150
|
+
},
|
|
151
|
+
'my-other-icons': async (iconName) => {
|
|
152
|
+
// your custom loader here. Do whatever you want.
|
|
153
|
+
// for example, fetch from a remote server:
|
|
154
|
+
return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
|
|
155
|
+
},
|
|
156
|
+
// a helper to load icons from the file system
|
|
157
|
+
// files under `./assets/icons` with `.svg` extension will be loaded as it's file name
|
|
158
|
+
// you can also provide a transform callback to change each icon (optional)
|
|
159
|
+
'my-yet-other-icons': FileSystemIconLoader(
|
|
160
|
+
'./assets/icons',
|
|
161
|
+
svg => svg.replace(/^<svg /, '<svg fill="currentColor" ')
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
]
|
|
166
|
+
})
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Icon Customizations
|
|
170
|
+
|
|
171
|
+
You can customize all icons using `customizations` configuration option.
|
|
172
|
+
|
|
173
|
+
Available customizations functions:
|
|
174
|
+
- `transform`: transform raw `svg`, will be only applied when using `custom` icon collection (`iconify` collections excluded).
|
|
175
|
+
- `customize`: change default icon customizations values.
|
|
176
|
+
- `iconCustomizer`: change default icon customizations values.
|
|
177
|
+
|
|
178
|
+
For each loaded icon, the customizations will be applied in this order:
|
|
179
|
+
- apply `transform` to raw `svg`, if provided and using custom icon collection
|
|
180
|
+
- apply `customize` with default customizations, if provided
|
|
181
|
+
- apply `iconCustomizer` with `customize` customizations, if provided
|
|
182
|
+
|
|
183
|
+
### Global Custom Icon Transformation
|
|
184
|
+
|
|
185
|
+
When loading your custom icons, you can transform them, for example adding `fill` attribute with `currentColor`:
|
|
186
|
+
```ts
|
|
187
|
+
UnoCss({
|
|
188
|
+
presets: [
|
|
189
|
+
presetIcons({
|
|
190
|
+
customizations: {
|
|
191
|
+
transform(svg) {
|
|
192
|
+
return svg.replace(/^<svg /, '<svg fill="currentColor" ')
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
})
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Global Icon Customization
|
|
201
|
+
|
|
202
|
+
When loading any icon you can customize common properties to all of them, for example configuring the same size:
|
|
203
|
+
```ts
|
|
204
|
+
UnoCss({
|
|
205
|
+
presets: [
|
|
206
|
+
presetIcons({
|
|
207
|
+
customizations: {
|
|
208
|
+
customize(props) {
|
|
209
|
+
props.width = '2em'
|
|
210
|
+
props.height = '2em'
|
|
211
|
+
return props
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
]
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Icon/Collection Customization
|
|
220
|
+
|
|
221
|
+
You can customize each icon using `iconCustomizer` configuration option.
|
|
222
|
+
|
|
223
|
+
The `iconCustomizer` will take precedence over configuration.
|
|
224
|
+
|
|
225
|
+
The `iconCustomizer` will be applied to any collection, that is, for each icon from `custom` loader, `inlined` on `custom collections` or from `@iconify`.
|
|
226
|
+
|
|
227
|
+
For example, you can configure `iconCustomizer` to change all icons for a collection or individual icons on a collection:
|
|
228
|
+
```ts
|
|
229
|
+
UnoCss({
|
|
230
|
+
presets: [
|
|
231
|
+
presetIcons({
|
|
232
|
+
customizations: {
|
|
233
|
+
iconCustomizer(collection, icon, props) {
|
|
234
|
+
// customize all icons in this collection
|
|
235
|
+
if (collection === 'my-other-icons') {
|
|
236
|
+
props.width = '4em'
|
|
237
|
+
props.height = '4em'
|
|
238
|
+
}
|
|
239
|
+
// customize this icon in this collection
|
|
240
|
+
if (collection === 'my-icons' && icon === 'account') {
|
|
241
|
+
props.width = '6em'
|
|
242
|
+
props.height = '6em'
|
|
243
|
+
}
|
|
244
|
+
// customize this @iconify icon in this collection
|
|
245
|
+
if (collection === 'mdi' && icon === 'account') {
|
|
246
|
+
props.width = '2em'
|
|
247
|
+
props.height = '2em'
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
]
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
85
256
|
## Credits
|
|
86
257
|
|
|
87
258
|
This preset is inspired from [this issue](https://github.com/antfu/unplugin-icons/issues/88) created by [@husayt](https://github.com/husayt). Based on the work of [this PR](https://github.com/antfu/unplugin-icons/pull/90) by [@userquin](https://github.com/userquin).
|
package/dist/index.cjs
CHANGED
|
@@ -3,53 +3,27 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const core = require('@unocss/core');
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const getIcon = require('@iconify/utils/lib/icon-set/get-icon');
|
|
6
|
+
const utils = require('@iconify/utils');
|
|
7
|
+
const encodeSvgForCss = require('@iconify/utils/lib/svg/encode-svg-for-css');
|
|
9
8
|
|
|
10
9
|
const isNode = typeof process < "u" && typeof process.stdout < "u";
|
|
11
10
|
const isVSCode = isNode && !!process.env.VSCODE_CWD;
|
|
12
|
-
function encodeSvg(svg) {
|
|
13
|
-
return svg.replace("<svg", ~svg.indexOf("xmlns") ? "<svg" : '<svg xmlns="http://www.w3.org/2000/svg"').replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/{/g, "%7B").replace(/}/g, "%7D").replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
14
|
-
}
|
|
15
11
|
|
|
16
12
|
const COLLECTION_NAME_PARTS_MAX = 3;
|
|
17
|
-
async function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} catch {
|
|
13
|
+
async function lookupIconLoader() {
|
|
14
|
+
let useIconLoader;
|
|
15
|
+
if (isNode && !isVSCode) {
|
|
21
16
|
try {
|
|
22
|
-
|
|
17
|
+
useIconLoader = await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
|
|
23
18
|
} catch {
|
|
24
|
-
|
|
19
|
+
try {
|
|
20
|
+
useIconLoader = require("@iconify/utils/lib/loader/node-loader.cjs");
|
|
21
|
+
} catch {
|
|
22
|
+
useIconLoader = utils.loadIcon;
|
|
23
|
+
}
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
|
-
|
|
28
|
-
async function searchForIcon(collection, id, collections, scale) {
|
|
29
|
-
if (!collection || !id)
|
|
30
|
-
return;
|
|
31
|
-
let iconSet = collections[collection];
|
|
32
|
-
if (typeof iconSet === "function")
|
|
33
|
-
iconSet = await iconSet();
|
|
34
|
-
if (!iconSet && isNode && !isVSCode) {
|
|
35
|
-
try {
|
|
36
|
-
const loadCollectionFromFS = await importFsModule().then((i) => i?.loadCollectionFromFS);
|
|
37
|
-
if (loadCollectionFromFS)
|
|
38
|
-
iconSet = await loadCollectionFromFS(collection);
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (!iconSet)
|
|
43
|
-
return;
|
|
44
|
-
const iconData = getIcon.getIconData(iconSet, id, true);
|
|
45
|
-
if (iconData) {
|
|
46
|
-
const { attributes, body } = build.iconToSVG(iconData, {
|
|
47
|
-
...customisations.defaults,
|
|
48
|
-
height: `${scale}em`,
|
|
49
|
-
width: `${scale}em`
|
|
50
|
-
});
|
|
51
|
-
return body.includes("xlink:") ? `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ${Object.entries(attributes).map((i) => `${i[0]}="${i[1]}"`).join(" ")}>${body}</svg>` : `<svg ${Object.entries(attributes).map((i) => `${i[0]}="${i[1]}"`).join(" ")}>${body}</svg>`;
|
|
52
|
-
}
|
|
26
|
+
return useIconLoader ?? utils.loadIcon;
|
|
53
27
|
}
|
|
54
28
|
const preset = (options = {}) => {
|
|
55
29
|
const {
|
|
@@ -57,8 +31,10 @@ const preset = (options = {}) => {
|
|
|
57
31
|
mode = "auto",
|
|
58
32
|
prefix = "i-",
|
|
59
33
|
warn = false,
|
|
60
|
-
collections
|
|
34
|
+
collections: customCollections,
|
|
61
35
|
extraProperties = {},
|
|
36
|
+
customizations = {},
|
|
37
|
+
autoInstall = false,
|
|
62
38
|
layer = "icons"
|
|
63
39
|
} = options;
|
|
64
40
|
return {
|
|
@@ -74,15 +50,29 @@ const preset = (options = {}) => {
|
|
|
74
50
|
let collection = "";
|
|
75
51
|
let name = "";
|
|
76
52
|
let svg;
|
|
53
|
+
const iconLoader = await lookupIconLoader();
|
|
54
|
+
const iconifyLoaderOptions = {
|
|
55
|
+
addXmlNs: true,
|
|
56
|
+
scale,
|
|
57
|
+
customCollections,
|
|
58
|
+
autoInstall,
|
|
59
|
+
warn: warn ? full : void 0,
|
|
60
|
+
customizations: {
|
|
61
|
+
...customizations,
|
|
62
|
+
additionalProps: { ...extraProperties },
|
|
63
|
+
trimCustomSvg: true
|
|
64
|
+
},
|
|
65
|
+
usedProps: {}
|
|
66
|
+
};
|
|
77
67
|
if (body.includes(":")) {
|
|
78
68
|
[collection, name] = body.split(":");
|
|
79
|
-
svg = await
|
|
69
|
+
svg = await iconLoader(collection, name, iconifyLoaderOptions);
|
|
80
70
|
} else {
|
|
81
71
|
const parts = body.split(/-/g);
|
|
82
72
|
for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
|
|
83
73
|
collection = parts.slice(0, i).join("-");
|
|
84
74
|
name = parts.slice(i).join("-");
|
|
85
|
-
svg = await
|
|
75
|
+
svg = await iconLoader(collection, name, iconifyLoaderOptions);
|
|
86
76
|
if (svg)
|
|
87
77
|
break;
|
|
88
78
|
}
|
|
@@ -95,7 +85,7 @@ const preset = (options = {}) => {
|
|
|
95
85
|
_mode = _mode || mode;
|
|
96
86
|
if (_mode === "auto")
|
|
97
87
|
_mode = svg.includes("currentColor") ? "mask" : "background-img";
|
|
98
|
-
const url = `url("data:image/svg+xml;utf8,${
|
|
88
|
+
const url = `url("data:image/svg+xml;utf8,${encodeSvgForCss.encodeSvgForCss(svg)}")`;
|
|
99
89
|
if (_mode === "mask") {
|
|
100
90
|
return {
|
|
101
91
|
"--un-icon": url,
|
|
@@ -104,18 +94,14 @@ const preset = (options = {}) => {
|
|
|
104
94
|
"-webkit-mask": "var(--un-icon) no-repeat",
|
|
105
95
|
"-webkit-mask-size": "100% 100%",
|
|
106
96
|
"background-color": "currentColor",
|
|
107
|
-
|
|
108
|
-
"width": `${scale}em`,
|
|
109
|
-
...extraProperties
|
|
97
|
+
...iconifyLoaderOptions.usedProps
|
|
110
98
|
};
|
|
111
99
|
} else {
|
|
112
100
|
return {
|
|
113
101
|
"background": `${url} no-repeat`,
|
|
114
102
|
"background-size": "100% 100%",
|
|
115
103
|
"background-color": "transparent",
|
|
116
|
-
|
|
117
|
-
"width": `${scale}em`,
|
|
118
|
-
...extraProperties
|
|
104
|
+
...iconifyLoaderOptions.usedProps
|
|
119
105
|
};
|
|
120
106
|
}
|
|
121
107
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Awaitable, Preset } from '@unocss/core';
|
|
2
|
+
import { CustomIconLoader, InlineCollection, IconCustomizations } from '@iconify/utils/lib/loader/types';
|
|
2
3
|
import { IconifyJSON } from '@iconify/types';
|
|
3
4
|
|
|
4
5
|
interface IconsOptions {
|
|
@@ -41,13 +42,25 @@ interface IconsOptions {
|
|
|
41
42
|
* In Node.js environment, the preset will search for the installed iconify dataset automatically.
|
|
42
43
|
* When using in the browser, this options is provided to provide dataset with custom loading mechanism.
|
|
43
44
|
*/
|
|
44
|
-
collections?: Record<string,
|
|
45
|
+
collections?: Record<string, (() => Awaitable<IconifyJSON>) | undefined | CustomIconLoader | InlineCollection>;
|
|
45
46
|
/**
|
|
46
47
|
* Rule layer
|
|
47
48
|
*
|
|
48
49
|
* @default 'icons'
|
|
49
50
|
*/
|
|
50
51
|
layer?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Custom icon customizations.
|
|
54
|
+
*/
|
|
55
|
+
customizations?: Omit<IconCustomizations, 'additionalProps' | 'trimCustomSvg'>;
|
|
56
|
+
/**
|
|
57
|
+
* Auto install icon sources package when the usages is detected
|
|
58
|
+
*
|
|
59
|
+
* **WARNING**: only on `node` environment, on `browser` this option will be ignored.
|
|
60
|
+
*
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
autoInstall?: boolean;
|
|
51
64
|
}
|
|
52
65
|
|
|
53
66
|
declare const preset: (options?: IconsOptions) => Preset;
|
package/dist/index.mjs
CHANGED
|
@@ -1,51 +1,25 @@
|
|
|
1
1
|
import { warnOnce } from '@unocss/core';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getIconData } from '@iconify/utils/lib/icon-set/get-icon';
|
|
2
|
+
import { loadIcon } from '@iconify/utils';
|
|
3
|
+
import { encodeSvgForCss } from '@iconify/utils/lib/svg/encode-svg-for-css';
|
|
5
4
|
|
|
6
5
|
const isNode = typeof process < "u" && typeof process.stdout < "u";
|
|
7
6
|
const isVSCode = isNode && !!process.env.VSCODE_CWD;
|
|
8
|
-
function encodeSvg(svg) {
|
|
9
|
-
return svg.replace("<svg", ~svg.indexOf("xmlns") ? "<svg" : '<svg xmlns="http://www.w3.org/2000/svg"').replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/{/g, "%7B").replace(/}/g, "%7D").replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
10
|
-
}
|
|
11
7
|
|
|
12
8
|
const COLLECTION_NAME_PARTS_MAX = 3;
|
|
13
|
-
async function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} catch {
|
|
9
|
+
async function lookupIconLoader() {
|
|
10
|
+
let useIconLoader;
|
|
11
|
+
if (isNode && !isVSCode) {
|
|
17
12
|
try {
|
|
18
|
-
|
|
13
|
+
useIconLoader = await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
|
|
19
14
|
} catch {
|
|
20
|
-
|
|
15
|
+
try {
|
|
16
|
+
useIconLoader = require("@iconify/utils/lib/loader/node-loader.cjs");
|
|
17
|
+
} catch {
|
|
18
|
+
useIconLoader = loadIcon;
|
|
19
|
+
}
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
|
|
24
|
-
async function searchForIcon(collection, id, collections, scale) {
|
|
25
|
-
if (!collection || !id)
|
|
26
|
-
return;
|
|
27
|
-
let iconSet = collections[collection];
|
|
28
|
-
if (typeof iconSet === "function")
|
|
29
|
-
iconSet = await iconSet();
|
|
30
|
-
if (!iconSet && isNode && !isVSCode) {
|
|
31
|
-
try {
|
|
32
|
-
const loadCollectionFromFS = await importFsModule().then((i) => i?.loadCollectionFromFS);
|
|
33
|
-
if (loadCollectionFromFS)
|
|
34
|
-
iconSet = await loadCollectionFromFS(collection);
|
|
35
|
-
} catch {
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (!iconSet)
|
|
39
|
-
return;
|
|
40
|
-
const iconData = getIconData(iconSet, id, true);
|
|
41
|
-
if (iconData) {
|
|
42
|
-
const { attributes, body } = iconToSVG(iconData, {
|
|
43
|
-
...defaults,
|
|
44
|
-
height: `${scale}em`,
|
|
45
|
-
width: `${scale}em`
|
|
46
|
-
});
|
|
47
|
-
return body.includes("xlink:") ? `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ${Object.entries(attributes).map((i) => `${i[0]}="${i[1]}"`).join(" ")}>${body}</svg>` : `<svg ${Object.entries(attributes).map((i) => `${i[0]}="${i[1]}"`).join(" ")}>${body}</svg>`;
|
|
48
|
-
}
|
|
22
|
+
return useIconLoader ?? loadIcon;
|
|
49
23
|
}
|
|
50
24
|
const preset = (options = {}) => {
|
|
51
25
|
const {
|
|
@@ -53,8 +27,10 @@ const preset = (options = {}) => {
|
|
|
53
27
|
mode = "auto",
|
|
54
28
|
prefix = "i-",
|
|
55
29
|
warn = false,
|
|
56
|
-
collections
|
|
30
|
+
collections: customCollections,
|
|
57
31
|
extraProperties = {},
|
|
32
|
+
customizations = {},
|
|
33
|
+
autoInstall = false,
|
|
58
34
|
layer = "icons"
|
|
59
35
|
} = options;
|
|
60
36
|
return {
|
|
@@ -70,15 +46,29 @@ const preset = (options = {}) => {
|
|
|
70
46
|
let collection = "";
|
|
71
47
|
let name = "";
|
|
72
48
|
let svg;
|
|
49
|
+
const iconLoader = await lookupIconLoader();
|
|
50
|
+
const iconifyLoaderOptions = {
|
|
51
|
+
addXmlNs: true,
|
|
52
|
+
scale,
|
|
53
|
+
customCollections,
|
|
54
|
+
autoInstall,
|
|
55
|
+
warn: warn ? full : void 0,
|
|
56
|
+
customizations: {
|
|
57
|
+
...customizations,
|
|
58
|
+
additionalProps: { ...extraProperties },
|
|
59
|
+
trimCustomSvg: true
|
|
60
|
+
},
|
|
61
|
+
usedProps: {}
|
|
62
|
+
};
|
|
73
63
|
if (body.includes(":")) {
|
|
74
64
|
[collection, name] = body.split(":");
|
|
75
|
-
svg = await
|
|
65
|
+
svg = await iconLoader(collection, name, iconifyLoaderOptions);
|
|
76
66
|
} else {
|
|
77
67
|
const parts = body.split(/-/g);
|
|
78
68
|
for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
|
|
79
69
|
collection = parts.slice(0, i).join("-");
|
|
80
70
|
name = parts.slice(i).join("-");
|
|
81
|
-
svg = await
|
|
71
|
+
svg = await iconLoader(collection, name, iconifyLoaderOptions);
|
|
82
72
|
if (svg)
|
|
83
73
|
break;
|
|
84
74
|
}
|
|
@@ -91,7 +81,7 @@ const preset = (options = {}) => {
|
|
|
91
81
|
_mode = _mode || mode;
|
|
92
82
|
if (_mode === "auto")
|
|
93
83
|
_mode = svg.includes("currentColor") ? "mask" : "background-img";
|
|
94
|
-
const url = `url("data:image/svg+xml;utf8,${
|
|
84
|
+
const url = `url("data:image/svg+xml;utf8,${encodeSvgForCss(svg)}")`;
|
|
95
85
|
if (_mode === "mask") {
|
|
96
86
|
return {
|
|
97
87
|
"--un-icon": url,
|
|
@@ -100,18 +90,14 @@ const preset = (options = {}) => {
|
|
|
100
90
|
"-webkit-mask": "var(--un-icon) no-repeat",
|
|
101
91
|
"-webkit-mask-size": "100% 100%",
|
|
102
92
|
"background-color": "currentColor",
|
|
103
|
-
|
|
104
|
-
"width": `${scale}em`,
|
|
105
|
-
...extraProperties
|
|
93
|
+
...iconifyLoaderOptions.usedProps
|
|
106
94
|
};
|
|
107
95
|
} else {
|
|
108
96
|
return {
|
|
109
97
|
"background": `${url} no-repeat`,
|
|
110
98
|
"background-size": "100% 100%",
|
|
111
99
|
"background-color": "transparent",
|
|
112
|
-
|
|
113
|
-
"width": `${scale}em`,
|
|
114
|
-
...extraProperties
|
|
100
|
+
...iconifyLoaderOptions.usedProps
|
|
115
101
|
};
|
|
116
102
|
}
|
|
117
103
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unocss/preset-icons",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Pure CSS Icons for UnoCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unocss",
|
|
@@ -29,11 +29,6 @@
|
|
|
29
29
|
"require": "./dist/index.cjs",
|
|
30
30
|
"import": "./dist/index.mjs",
|
|
31
31
|
"types": "./dist/index.d.ts"
|
|
32
|
-
},
|
|
33
|
-
"./fs": {
|
|
34
|
-
"require": "./dist/fs.cjs",
|
|
35
|
-
"import": "./dist/fs.mjs",
|
|
36
|
-
"types": "./dist/fs.d.ts"
|
|
37
32
|
}
|
|
38
33
|
},
|
|
39
34
|
"files": [
|
|
@@ -42,16 +37,15 @@
|
|
|
42
37
|
],
|
|
43
38
|
"sideEffects": false,
|
|
44
39
|
"dependencies": {
|
|
45
|
-
"@iconify/utils": "^1.0.
|
|
46
|
-
"@unocss/core": "0.
|
|
47
|
-
"local-pkg": "^0.4.1"
|
|
40
|
+
"@iconify/utils": "^1.0.30",
|
|
41
|
+
"@unocss/core": "0.30.0"
|
|
48
42
|
},
|
|
49
43
|
"devDependencies": {
|
|
50
|
-
"@iconify/types": "^1.0
|
|
44
|
+
"@iconify/types": "^1.1.0"
|
|
51
45
|
},
|
|
52
46
|
"scripts": {
|
|
53
47
|
"build": "unbuild",
|
|
54
48
|
"stub": "unbuild --stub"
|
|
55
49
|
},
|
|
56
|
-
"readme": "# @unocss/preset-icons\n\nUse **any** icons with **Pure CSS** for [UnoCSS](https://github.com/unocss/unocss).\n\n<blockquote>\n<p>💡 Recommend reading - <br><a href=\"https://antfu.me/posts/icons-in-pure-css\"><strong>Icons in Pure CSS</strong></a><br></p>\n</blockquote>\n\nFollow the following conventions to use the icons\n\n- `<prefix><collection>-<icon>`\n- `<prefix><collection>:<icon>`\n\nFor examples:\n\n```html\n<!-- A basic anchor icon from Phosphor icons -->\n<div class=\"i-ph-anchor-simple-thin\" />\n<!-- An orange alarm from Material Design Icons -->\n<div class=\"i-mdi-alarm text-orange-400\" />\n<!-- A large Vue logo -->\n<div class=\"i-logos-vue text-3xl\" />\n<!-- Sun in light mode, Moon in dark mode, from Carbon -->\n<button class=\"i-carbon-sun dark:i-carbon-moon\" />\n<!-- Twemoji of laugh, turns to tear on hovering -->\n<div class=\"i-twemoji-grinning-face-with-smiling-eyes hover:i-twemoji-face-with-tears-of-joy\" />\n```\n\n<img src=\"https://user-images.githubusercontent.com/11247099/136709053-31b4db79-eddc-4dc6-aa2d-388086332630.gif\" height=\"100\"><br><sup>This is powered by pure CSS</sup>\n\n## Install\n\n```bash\nnpm i -D @unocss/preset-icons @iconify-json/[the-collection-you-want]\n```\n\nWe use [Iconify](https://iconify.design) as our data source of icons. You need to install the corresponding iconset in `devDependencies` by following the `@iconify-json/*` pattern. For example, `@iconify-json/mdi` for [Material Design Icons](https://materialdesignicons.com/), `@iconify-json/tabler` for [Tabler](https://tabler-icons.io/). You can refer to [Icônes](https://icones.js.org/) or [Iconify](https://icon-sets.iconify.design/) for all the collections available.\n\n```ts\nimport presetIcons from '@unocss/preset-icons'\n\nUnocss({\n presets: [\n presetIcons({ /* options */ }),\n // ...other presets\n ],\n})\n```\n\n> 💡 You can also use this preset alone as a complement to your existing UI frameworks to have pure CSS icons!\n\nIf you prefer to install the all the icon sets available on Iconify at once (~130MB):\n\n```bash\nnpm i -D @iconify/json\n```\n\n## Configuration\n\nRefer to the [type definition](https://github.com/unocss/unocss/blob/main/packages/preset-icons/src/types.ts#L4) for all configurations avaliable.\n\n### Extra Properties\n\nYou can provide the extra CSS properties to control the default behavior of the icons. The following is an example of make icons inlined by default:\n\n```ts\npresetIcons({\n extraProperties: {\n 'display': 'inline-block',\n 'vertical-align': 'middle',\n // ...\n },\n})\n```\n\n## Modes Overriding\n\nBy default, this preset will choose the rendering modes automatically for each icon based on the icons' characteristics. You can read more in this [blog post](https://antfu.me/posts/icons-in-pure-css). In some cases, you may want to explicitly set the rendering modes for each icon.\n\n- `?bg` for `background-img` - renders the icon as a background image\n- `?mask` for `mask` - renders the icon as a mask image\n\nfor example, `vscode-icons:file-type-light-db`, an icon with colors that will be rendered as a background image. Use `vscode-icons:file-type-light-db?bg` to render it as a mask image and bypass it's colors.\n\n## Credits\n\nThis preset is inspired from [this issue](https://github.com/antfu/unplugin-icons/issues/88) created by [@husayt](https://github.com/husayt). Based on the work of [this PR](https://github.com/antfu/unplugin-icons/pull/90) by [@userquin](https://github.com/userquin).\n\n## License\n\nMIT License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)\n"
|
|
50
|
+
"readme": "# @unocss/preset-icons\n\nUse **any** icons with **Pure CSS** for [UnoCSS](https://github.com/unocss/unocss).\n\n<blockquote>\n<p>💡 Recommend reading - <br><a href=\"https://antfu.me/posts/icons-in-pure-css\"><strong>Icons in Pure CSS</strong></a><br></p>\n</blockquote>\n\nFollow the following conventions to use the icons\n\n- `<prefix><collection>-<icon>`\n- `<prefix><collection>:<icon>`\n\nFor examples:\n\n```html\n<!-- A basic anchor icon from Phosphor icons -->\n<div class=\"i-ph-anchor-simple-thin\" />\n<!-- An orange alarm from Material Design Icons -->\n<div class=\"i-mdi-alarm text-orange-400\" />\n<!-- A large Vue logo -->\n<div class=\"i-logos-vue text-3xl\" />\n<!-- Sun in light mode, Moon in dark mode, from Carbon -->\n<button class=\"i-carbon-sun dark:i-carbon-moon\" />\n<!-- Twemoji of laugh, turns to tear on hovering -->\n<div class=\"i-twemoji-grinning-face-with-smiling-eyes hover:i-twemoji-face-with-tears-of-joy\" />\n```\n\n<img src=\"https://user-images.githubusercontent.com/11247099/136709053-31b4db79-eddc-4dc6-aa2d-388086332630.gif\" height=\"100\"><br><sup>This is powered by pure CSS</sup>\n\n## Install\n\n```bash\nnpm i -D @unocss/preset-icons @iconify-json/[the-collection-you-want]\n```\n\nWe use [Iconify](https://iconify.design) as our data source of icons. You need to install the corresponding iconset in `devDependencies` by following the `@iconify-json/*` pattern. For example, `@iconify-json/mdi` for [Material Design Icons](https://materialdesignicons.com/), `@iconify-json/tabler` for [Tabler](https://tabler-icons.io/). You can refer to [Icônes](https://icones.js.org/) or [Iconify](https://icon-sets.iconify.design/) for all the collections available.\n\n```ts\nimport presetIcons from '@unocss/preset-icons'\n\nUnocss({\n presets: [\n presetIcons({ /* options */ }),\n // ...other presets\n ],\n})\n```\n\n> 💡 You can also use this preset alone as a complement to your existing UI frameworks to have pure CSS icons!\n\nIf you prefer to install the all the icon sets available on Iconify at once (~130MB):\n\n```bash\nnpm i -D @iconify/json\n```\n\n## Configuration\n\nRefer to the [type definition](https://github.com/unocss/unocss/blob/main/packages/preset-icons/src/types.ts#L4) for all configurations avaliable.\n\n### Extra Properties\n\nYou can provide the extra CSS properties to control the default behavior of the icons. The following is an example of make icons inlined by default:\n\n```ts\npresetIcons({\n extraProperties: {\n 'display': 'inline-block',\n 'vertical-align': 'middle',\n // ...\n },\n})\n```\n\n## Modes Overriding\n\nBy default, this preset will choose the rendering modes automatically for each icon based on the icons' characteristics. You can read more in this [blog post](https://antfu.me/posts/icons-in-pure-css). In some cases, you may want to explicitly set the rendering modes for each icon.\n\n- `?bg` for `background-img` - renders the icon as a background image\n- `?mask` for `mask` - renders the icon as a mask image\n\nfor example, `vscode-icons:file-type-light-db`, an icon with colors that will be rendered as a background image. Use `vscode-icons:file-type-light-db?bg` to render it as a mask image and bypass it's colors.\n\n## Configuring collections and icons resolvers\n\nYou can provide collections via `@iconify-json/[the-collection-you-want]`, `@iconify/json` or using your custom ones using `collections` option on your `UnoCSS` configuration.\n\n### Browser\n\nTo load `iconify` collections you should use `@iconify-json/[the-collection-you-want]` and not `@iconify/json` since the `json` file is huge.\nYou will need to provide the `iconify` collections using `dynamic imports`, for example, on playground you have these collections:\n```ts\npresetIcons({\n collections: {\n carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any),\n mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default as any),\n logos: () => import('@iconify-json/logos/icons.json').then(i => i.default as any),\n twemoji: () => import('@iconify-json/twemoji/icons.json').then(i => i.default as any),\n ri: () => import('@iconify-json/ri/icons.json').then(i => i.default as any),\n tabler: () => import('@iconify-json/tabler/icons.json').then(i => i.default as any),\n uim: () => import('@iconify-json/uim/icons.json').then(i => i.default as any)\n }\n})\n```\n\nYou can also provide your own custom collections using [CustomIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L12) or [InlineCollection](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L61), for example using `InlineCollection`:\n```ts\nUnoCss({\n presets: [\n presetIcons({\n collections: {\n custom: {\n circle: '<svg viewBox=\"0 0 120 120\"><circle cx=\"60\" cy=\"60\" r=\"50\"></circle></svg>',\n /* ... */\n },\n carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any),\n /* ... */\n }\n })\n ]\n})\n```\n\nand then, you can use it on your html: `<span class=\"i-custom:circle\"></span>`\n\n### Node.js\n\nIn `Node.js` the preset will search for the installed iconify dataset automatically and so you don't need to register the `iconify` collections.\n\nYou can also provide your own custom collections using also [CustomIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L12) or [InlineCollection](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L61).\n\nAdditionally, you can also use [FileSystemIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/loaders.ts#L9) to load your custom icons from your file system. You will need to install `@iconify/utils` package as `dev dependency`.\n```ts\n// vite.config.ts\nimport { promises as fs } from 'fs'\n// loader helpers\nimport { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'\n\nUnoCss({\n presets: [ \n presetIcons({\n collections: {\n // key as the collection name\n 'my-icons': {\n 'account': '<svg><!-- ... --></svg>',\n // load your custom icon lazily\n 'settings': () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),\n /* ... */\n },\n 'my-other-icons': async (iconName) => {\n // your custom loader here. Do whatever you want.\n // for example, fetch from a remote server: \n return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())\n },\n // a helper to load icons from the file system\n // files under `./assets/icons` with `.svg` extension will be loaded as it's file name\n // you can also provide a transform callback to change each icon (optional)\n 'my-yet-other-icons': FileSystemIconLoader(\n './assets/icons',\n svg => svg.replace(/^<svg /, '<svg fill=\"currentColor\" ')\n )\n }\n })\n ]\n})\n```\n\n## Icon Customizations\n\nYou can customize all icons using `customizations` configuration option. \n\nAvailable customizations functions:\n- `transform`: transform raw `svg`, will be only applied when using `custom` icon collection (`iconify` collections excluded).\n- `customize`: change default icon customizations values.\n- `iconCustomizer`: change default icon customizations values.\n\nFor each loaded icon, the customizations will be applied in this order:\n- apply `transform` to raw `svg`, if provided and using custom icon collection\n- apply `customize` with default customizations, if provided\n- apply `iconCustomizer` with `customize` customizations, if provided\n\n### Global Custom Icon Transformation\n\nWhen loading your custom icons, you can transform them, for example adding `fill` attribute with `currentColor`:\n```ts\nUnoCss({\n presets: [\n presetIcons({\n customizations: {\n transform(svg) {\n return svg.replace(/^<svg /, '<svg fill=\"currentColor\" ') \n }\n }\n })\n ]\n})\n```\n\n### Global Icon Customization\n\nWhen loading any icon you can customize common properties to all of them, for example configuring the same size:\n```ts\nUnoCss({\n presets: [\n presetIcons({\n customizations: {\n customize(props) {\n props.width = '2em'\n props.height = '2em'\n return props\n }\n }\n })\n ]\n})\n```\n\n### Icon/Collection Customization\n\nYou can customize each icon using `iconCustomizer` configuration option.\n\nThe `iconCustomizer` will take precedence over configuration.\n\nThe `iconCustomizer` will be applied to any collection, that is, for each icon from `custom` loader, `inlined` on `custom collections` or from `@iconify`.\n\nFor example, you can configure `iconCustomizer` to change all icons for a collection or individual icons on a collection:\n```ts\nUnoCss({\n presets: [\n presetIcons({\n customizations: {\n iconCustomizer(collection, icon, props) {\n // customize all icons in this collection \n if (collection === 'my-other-icons') {\n props.width = '4em'\n props.height = '4em'\n }\n // customize this icon in this collection\n if (collection === 'my-icons' && icon === 'account') {\n props.width = '6em'\n props.height = '6em'\n }\n // customize this @iconify icon in this collection \n if (collection === 'mdi' && icon === 'account') {\n props.width = '2em'\n props.height = '2em'\n }\n }\n }\n })\n ]\n}) \n```\n\n## Credits\n\nThis preset is inspired from [this issue](https://github.com/antfu/unplugin-icons/issues/88) created by [@husayt](https://github.com/husayt). Based on the work of [this PR](https://github.com/antfu/unplugin-icons/pull/90) by [@userquin](https://github.com/userquin).\n\n## License\n\nMIT License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)\n"
|
|
57
51
|
}
|
package/dist/fs.cjs
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const localPkg = require('local-pkg');
|
|
7
|
-
|
|
8
|
-
const _collections = {};
|
|
9
|
-
const isLegacyExists = localPkg.isPackageExists("@iconify/json");
|
|
10
|
-
async function loadCollectionFromFS(name) {
|
|
11
|
-
if (!_collections[name])
|
|
12
|
-
_collections[name] = task();
|
|
13
|
-
return _collections[name];
|
|
14
|
-
async function task() {
|
|
15
|
-
let jsonPath = localPkg.resolveModule(`@iconify-json/${name}/icons.json`);
|
|
16
|
-
if (!jsonPath && isLegacyExists)
|
|
17
|
-
jsonPath = localPkg.resolveModule(`@iconify/json/json/${name}.json`);
|
|
18
|
-
if (jsonPath) {
|
|
19
|
-
const icons = JSON.parse(await fs.promises.readFile(jsonPath, "utf8"));
|
|
20
|
-
return icons;
|
|
21
|
-
} else {
|
|
22
|
-
return void 0;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
exports.loadCollectionFromFS = loadCollectionFromFS;
|
package/dist/fs.d.ts
DELETED
package/dist/fs.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { promises } from 'fs';
|
|
2
|
-
import { isPackageExists, resolveModule } from 'local-pkg';
|
|
3
|
-
|
|
4
|
-
const _collections = {};
|
|
5
|
-
const isLegacyExists = isPackageExists("@iconify/json");
|
|
6
|
-
async function loadCollectionFromFS(name) {
|
|
7
|
-
if (!_collections[name])
|
|
8
|
-
_collections[name] = task();
|
|
9
|
-
return _collections[name];
|
|
10
|
-
async function task() {
|
|
11
|
-
let jsonPath = resolveModule(`@iconify-json/${name}/icons.json`);
|
|
12
|
-
if (!jsonPath && isLegacyExists)
|
|
13
|
-
jsonPath = resolveModule(`@iconify/json/json/${name}.json`);
|
|
14
|
-
if (jsonPath) {
|
|
15
|
-
const icons = JSON.parse(await promises.readFile(jsonPath, "utf8"));
|
|
16
|
-
return icons;
|
|
17
|
-
} else {
|
|
18
|
-
return void 0;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export { loadCollectionFromFS };
|