@unocss/preset-icons 0.32.8 → 0.32.12

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 CHANGED
@@ -89,18 +89,33 @@ You can provide collections via `@iconify-json/[the-collection-you-want]`, `@ico
89
89
  ### Browser
90
90
 
91
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:
92
+
93
+ #### Bundler
94
+
95
+ When using bundlers, you can provide the collections using `dynamic imports` so they will be bundler as async chunk and loaded on demand.
93
96
 
94
97
  ```ts
95
98
  presetIcons({
96
99
  collections: {
97
- carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any),
98
- mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default as any),
99
- logos: () => import('@iconify-json/logos/icons.json').then(i => i.default as any),
100
+ carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default),
101
+ mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default),
102
+ logos: () => import('@iconify-json/logos/icons.json').then(i => i.default),
100
103
  }
101
104
  })
102
105
  ```
103
106
 
107
+ #### CDN
108
+
109
+ Or if you prefer to fetch them from CDN, you can specify the `cdn` option since `v0.32.10`. We recommend [esm.sh](https://esm.sh/) as the CDN provider.
110
+
111
+ ```ts
112
+ presetIcons({
113
+ cdn: 'https://esm.sh/'
114
+ })
115
+ ```
116
+
117
+ #### Customization
118
+
104
119
  You can also provide your own custom collections using [CustomIconLoader](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L17) or [InlineCollection](https://github.com/iconify/iconify/blob/master/packages/utils/src/loader/types.ts#L86), for example using `InlineCollection`:
105
120
 
106
121
  ```ts
package/dist/index.cjs CHANGED
@@ -5,26 +5,444 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  const core = require('@unocss/core');
6
6
  const utils = require('@iconify/utils');
7
7
  const encodeSvgForCss = require('@iconify/utils/lib/svg/encode-svg-for-css');
8
+ const loader = require('@iconify/utils/lib/loader/loader');
9
+ const modern = require('@iconify/utils/lib/loader/modern');
8
10
 
9
11
  const isNode = typeof process < "u" && typeof process.stdout < "u" && !process.versions.deno;
10
12
  const isVSCode = isNode && !!process.env.VSCODE_CWD;
11
13
 
12
- const COLLECTION_NAME_PARTS_MAX = 3;
13
- async function lookupIconLoader() {
14
- let useIconLoader;
15
- if (isNode && !isVSCode) {
16
- try {
17
- useIconLoader = await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
18
- } catch {
19
- try {
20
- useIconLoader = require("@iconify/utils/lib/loader/node-loader.cjs");
21
- } catch {
22
- useIconLoader = utils.loadIcon;
14
+ const suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
15
+ const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
16
+ const JsonSigRx = /^["{[]|^-?[0-9][0-9.]{0,14}$/;
17
+ function jsonParseTransform(key, value) {
18
+ if (key === "__proto__" || key === "constructor") {
19
+ return;
20
+ }
21
+ return value;
22
+ }
23
+ function destr(val) {
24
+ if (typeof val !== "string") {
25
+ return val;
26
+ }
27
+ const _lval = val.toLowerCase();
28
+ if (_lval === "true") {
29
+ return true;
30
+ }
31
+ if (_lval === "false") {
32
+ return false;
33
+ }
34
+ if (_lval === "null") {
35
+ return null;
36
+ }
37
+ if (_lval === "nan") {
38
+ return NaN;
39
+ }
40
+ if (_lval === "infinity") {
41
+ return Infinity;
42
+ }
43
+ if (_lval === "undefined") {
44
+ return void 0;
45
+ }
46
+ if (!JsonSigRx.test(val)) {
47
+ return val;
48
+ }
49
+ try {
50
+ if (suspectProtoRx.test(val) || suspectConstructorRx.test(val)) {
51
+ return JSON.parse(val, jsonParseTransform);
52
+ }
53
+ return JSON.parse(val);
54
+ } catch (_e) {
55
+ return val;
56
+ }
57
+ }
58
+
59
+ const HASH_RE = /#/g;
60
+ const AMPERSAND_RE = /&/g;
61
+ const EQUAL_RE = /=/g;
62
+ const PLUS_RE = /\+/g;
63
+ const ENC_BRACKET_OPEN_RE = /%5B/gi;
64
+ const ENC_BRACKET_CLOSE_RE = /%5D/gi;
65
+ const ENC_CARET_RE = /%5E/gi;
66
+ const ENC_BACKTICK_RE = /%60/gi;
67
+ const ENC_CURLY_OPEN_RE = /%7B/gi;
68
+ const ENC_PIPE_RE = /%7C/gi;
69
+ const ENC_CURLY_CLOSE_RE = /%7D/gi;
70
+ const ENC_SPACE_RE = /%20/gi;
71
+ function encode(text) {
72
+ return encodeURI("" + text).replace(ENC_PIPE_RE, "|").replace(ENC_BRACKET_OPEN_RE, "[").replace(ENC_BRACKET_CLOSE_RE, "]");
73
+ }
74
+ function encodeQueryValue(text) {
75
+ return encode(text).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CURLY_OPEN_RE, "{").replace(ENC_CURLY_CLOSE_RE, "}").replace(ENC_CARET_RE, "^");
76
+ }
77
+ function encodeQueryKey(text) {
78
+ return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
79
+ }
80
+ function decode(text = "") {
81
+ try {
82
+ return decodeURIComponent("" + text);
83
+ } catch (_err) {
84
+ return "" + text;
85
+ }
86
+ }
87
+ function decodeQueryValue(text) {
88
+ return decode(text.replace(PLUS_RE, " "));
89
+ }
90
+
91
+ function parseQuery(paramsStr = "") {
92
+ const obj = {};
93
+ if (paramsStr[0] === "?") {
94
+ paramsStr = paramsStr.substr(1);
95
+ }
96
+ for (const param of paramsStr.split("&")) {
97
+ const s = param.match(/([^=]+)=?(.*)/) || [];
98
+ if (s.length < 2) {
99
+ continue;
100
+ }
101
+ const key = decode(s[1]);
102
+ if (key === "__proto__" || key === "constructor") {
103
+ continue;
104
+ }
105
+ const value = decodeQueryValue(s[2] || "");
106
+ if (obj[key]) {
107
+ if (Array.isArray(obj[key])) {
108
+ obj[key].push(value);
109
+ } else {
110
+ obj[key] = [obj[key], value];
111
+ }
112
+ } else {
113
+ obj[key] = value;
114
+ }
115
+ }
116
+ return obj;
117
+ }
118
+ function encodeQueryItem(key, val) {
119
+ if (typeof val === "number" || typeof val === "boolean") {
120
+ val = String(val);
121
+ }
122
+ if (!val) {
123
+ return encodeQueryKey(key);
124
+ }
125
+ if (Array.isArray(val)) {
126
+ return val.map((_val) => `${encodeQueryKey(key)}=${encodeQueryValue(_val)}`).join("&");
127
+ }
128
+ return `${encodeQueryKey(key)}=${encodeQueryValue(val)}`;
129
+ }
130
+ function stringifyQuery(query) {
131
+ return Object.keys(query).map((k) => encodeQueryItem(k, query[k])).join("&");
132
+ }
133
+ const PROTOCOL_REGEX = /^\w+:(\/\/)?/;
134
+ const PROTOCOL_RELATIVE_REGEX = /^\/\/[^/]+/;
135
+ function hasProtocol(inputStr, acceptProtocolRelative = false) {
136
+ return PROTOCOL_REGEX.test(inputStr) || acceptProtocolRelative && PROTOCOL_RELATIVE_REGEX.test(inputStr);
137
+ }
138
+ const TRAILING_SLASH_RE = /\/$|\/\?/;
139
+ function hasTrailingSlash(input = "", queryParams = false) {
140
+ if (!queryParams) {
141
+ return input.endsWith("/");
142
+ }
143
+ return TRAILING_SLASH_RE.test(input);
144
+ }
145
+ function withoutTrailingSlash(input = "", queryParams = false) {
146
+ if (!queryParams) {
147
+ return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
148
+ }
149
+ if (!hasTrailingSlash(input, true)) {
150
+ return input || "/";
151
+ }
152
+ const [s0, ...s] = input.split("?");
153
+ return (s0.slice(0, -1) || "/") + (s.length ? `?${s.join("?")}` : "");
154
+ }
155
+ function withTrailingSlash(input = "", queryParams = false) {
156
+ if (!queryParams) {
157
+ return input.endsWith("/") ? input : input + "/";
158
+ }
159
+ if (hasTrailingSlash(input, true)) {
160
+ return input || "/";
161
+ }
162
+ const [s0, ...s] = input.split("?");
163
+ return s0 + "/" + (s.length ? `?${s.join("?")}` : "");
164
+ }
165
+ function hasLeadingSlash(input = "") {
166
+ return input.startsWith("/");
167
+ }
168
+ function withoutLeadingSlash(input = "") {
169
+ return (hasLeadingSlash(input) ? input.substr(1) : input) || "/";
170
+ }
171
+ function withBase(input, base) {
172
+ if (isEmptyURL(base)) {
173
+ return input;
174
+ }
175
+ const _base = withoutTrailingSlash(base);
176
+ if (input.startsWith(_base)) {
177
+ return input;
178
+ }
179
+ return joinURL(_base, input);
180
+ }
181
+ function withQuery(input, query) {
182
+ const parsed = parseURL(input);
183
+ const mergedQuery = { ...parseQuery(parsed.search), ...query };
184
+ parsed.search = stringifyQuery(mergedQuery);
185
+ return stringifyParsedURL(parsed);
186
+ }
187
+ function isEmptyURL(url) {
188
+ return !url || url === "/";
189
+ }
190
+ function isNonEmptyURL(url) {
191
+ return url && url !== "/";
192
+ }
193
+ function joinURL(base, ...input) {
194
+ let url = base || "";
195
+ for (const i of input.filter(isNonEmptyURL)) {
196
+ url = url ? withTrailingSlash(url) + withoutLeadingSlash(i) : i;
197
+ }
198
+ return url;
199
+ }
200
+
201
+ function parseURL(input = "", defaultProto) {
202
+ if (!hasProtocol(input, true)) {
203
+ return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
204
+ }
205
+ const [protocol = "", auth, hostAndPath = ""] = (input.replace(/\\/g, "/").match(/([^:/]+:)?\/\/([^/@]+@)?(.*)/) || []).splice(1);
206
+ const [host = "", path = ""] = (hostAndPath.match(/([^/?#]*)(.*)?/) || []).splice(1);
207
+ const { pathname, search, hash } = parsePath(path);
208
+ return {
209
+ protocol,
210
+ auth: auth ? auth.substr(0, auth.length - 1) : "",
211
+ host,
212
+ pathname,
213
+ search,
214
+ hash
215
+ };
216
+ }
217
+ function parsePath(input = "") {
218
+ const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
219
+ return {
220
+ pathname,
221
+ search,
222
+ hash
223
+ };
224
+ }
225
+ function stringifyParsedURL(parsed) {
226
+ const fullpath = parsed.pathname + (parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "") + parsed.hash;
227
+ if (!parsed.protocol) {
228
+ return fullpath;
229
+ }
230
+ return parsed.protocol + "//" + (parsed.auth ? parsed.auth + "@" : "") + parsed.host + fullpath;
231
+ }
232
+
233
+ class FetchError extends Error {
234
+ constructor() {
235
+ super(...arguments);
236
+ this.name = "FetchError";
237
+ }
238
+ }
239
+ function createFetchError(request, error, response) {
240
+ let message = "";
241
+ if (request && response) {
242
+ message = `${response.status} ${response.statusText} (${request.toString()})`;
243
+ }
244
+ if (error) {
245
+ message = `${error.message} (${message})`;
246
+ }
247
+ const fetchError = new FetchError(message);
248
+ Object.defineProperty(fetchError, "request", { get() {
249
+ return request;
250
+ } });
251
+ Object.defineProperty(fetchError, "response", { get() {
252
+ return response;
253
+ } });
254
+ Object.defineProperty(fetchError, "data", { get() {
255
+ return response && response._data;
256
+ } });
257
+ return fetchError;
258
+ }
259
+
260
+ const payloadMethods = new Set(Object.freeze(["PATCH", "POST", "PUT", "DELETE"]));
261
+ function isPayloadMethod(method = "GET") {
262
+ return payloadMethods.has(method.toUpperCase());
263
+ }
264
+ function isJSONSerializable(val) {
265
+ if (val === void 0) {
266
+ return false;
267
+ }
268
+ const t = typeof val;
269
+ if (t === "string" || t === "number" || t === "boolean" || t === null) {
270
+ return true;
271
+ }
272
+ if (t !== "object") {
273
+ return false;
274
+ }
275
+ if (Array.isArray(val)) {
276
+ return true;
277
+ }
278
+ return val.constructor && val.constructor.name === "Object" || typeof val.toJSON === "function";
279
+ }
280
+ const textTypes = /* @__PURE__ */ new Set([
281
+ "image/svg",
282
+ "application/xml",
283
+ "application/xhtml",
284
+ "application/html"
285
+ ]);
286
+ const JSON_RE = /^application\/(?:[\w!#$%&*`\-.^~]*\+)?json(;.+)?$/i;
287
+ function detectResponseType(_contentType = "") {
288
+ if (!_contentType) {
289
+ return "json";
290
+ }
291
+ const contentType = _contentType.split(";").shift();
292
+ if (JSON_RE.test(contentType)) {
293
+ return "json";
294
+ }
295
+ if (textTypes.has(contentType) || contentType.startsWith("text/")) {
296
+ return "text";
297
+ }
298
+ return "blob";
299
+ }
300
+
301
+ const retryStatusCodes = /* @__PURE__ */ new Set([
302
+ 408,
303
+ 409,
304
+ 425,
305
+ 429,
306
+ 500,
307
+ 502,
308
+ 503,
309
+ 504
310
+ ]);
311
+ function createFetch(globalOptions) {
312
+ const { fetch, Headers } = globalOptions;
313
+ function onError(ctx) {
314
+ if (ctx.options.retry !== false) {
315
+ const retries = typeof ctx.options.retry === "number" ? ctx.options.retry : isPayloadMethod(ctx.options.method) ? 0 : 1;
316
+ const responseCode = ctx.response && ctx.response.status || 500;
317
+ if (retries > 0 && retryStatusCodes.has(responseCode)) {
318
+ return $fetchRaw(ctx.request, {
319
+ ...ctx.options,
320
+ retry: retries - 1
321
+ });
322
+ }
323
+ }
324
+ const err = createFetchError(ctx.request, ctx.error, ctx.response);
325
+ if (Error.captureStackTrace) {
326
+ Error.captureStackTrace(err, $fetchRaw);
327
+ }
328
+ throw err;
329
+ }
330
+ const $fetchRaw = async function $fetchRaw2(_request, _opts = {}) {
331
+ const ctx = {
332
+ request: _request,
333
+ options: { ...globalOptions.defaults, ..._opts },
334
+ response: void 0,
335
+ error: void 0
336
+ };
337
+ if (ctx.options.onRequest) {
338
+ await ctx.options.onRequest(ctx);
339
+ }
340
+ if (typeof ctx.request === "string") {
341
+ if (ctx.options.baseURL) {
342
+ ctx.request = withBase(ctx.request, ctx.options.baseURL);
343
+ }
344
+ if (ctx.options.params) {
345
+ ctx.request = withQuery(ctx.request, ctx.options.params);
346
+ }
347
+ if (ctx.options.body && isPayloadMethod(ctx.options.method)) {
348
+ if (isJSONSerializable(ctx.options.body)) {
349
+ ctx.options.body = JSON.stringify(ctx.options.body);
350
+ ctx.options.headers = new Headers(ctx.options.headers);
351
+ if (!ctx.options.headers.has("content-type")) {
352
+ ctx.options.headers.set("content-type", "application/json");
353
+ }
354
+ if (!ctx.options.headers.has("accept")) {
355
+ ctx.options.headers.set("accept", "application/json");
356
+ }
357
+ }
23
358
  }
24
359
  }
360
+ ctx.response = await fetch(ctx.request, ctx.options).catch(async (error) => {
361
+ ctx.error = error;
362
+ if (ctx.options.onRequestError) {
363
+ await ctx.options.onRequestError(ctx);
364
+ }
365
+ return onError(ctx);
366
+ });
367
+ const responseType = (ctx.options.parseResponse ? "json" : ctx.options.responseType) || detectResponseType(ctx.response.headers.get("content-type") || "");
368
+ if (responseType === "json") {
369
+ const data = await ctx.response.text();
370
+ const parseFn = ctx.options.parseResponse || destr;
371
+ ctx.response._data = parseFn(data);
372
+ } else {
373
+ ctx.response._data = await ctx.response[responseType]();
374
+ }
375
+ if (ctx.options.onResponse) {
376
+ await ctx.options.onResponse(ctx);
377
+ }
378
+ if (!ctx.response.ok) {
379
+ if (ctx.options.onResponseError) {
380
+ await ctx.options.onResponseError(ctx);
381
+ }
382
+ }
383
+ return ctx.response.ok ? ctx.response : onError(ctx);
384
+ };
385
+ const $fetch = function $fetch2(request, opts) {
386
+ return $fetchRaw(request, opts).then((r) => r._data);
387
+ };
388
+ $fetch.raw = $fetchRaw;
389
+ $fetch.create = (defaultOptions = {}) => createFetch({
390
+ ...globalOptions,
391
+ defaults: {
392
+ ...globalOptions.defaults,
393
+ ...defaultOptions
394
+ }
395
+ });
396
+ return $fetch;
397
+ }
398
+
399
+ const _globalThis = function() {
400
+ if (typeof globalThis !== "undefined") {
401
+ return globalThis;
402
+ }
403
+ if (typeof self !== "undefined") {
404
+ return self;
405
+ }
406
+ if (typeof window !== "undefined") {
407
+ return window;
25
408
  }
26
- return useIconLoader ?? utils.loadIcon;
409
+ if (typeof global !== "undefined") {
410
+ return global;
411
+ }
412
+ throw new Error("unable to locate global object");
413
+ }();
414
+ const fetch = _globalThis.fetch || (() => Promise.reject(new Error("[ohmyfetch] global.fetch is not supported!")));
415
+ const Headers = _globalThis.Headers;
416
+ const $fetch = createFetch({ fetch, Headers });
417
+
418
+ const supportedCollection = ["material-symbols", "ic", "mdi", "ph", "ri", "carbon", "bi", "tabler", "ion", "uil", "teenyicons", "clarity", "iconoir", "majesticons", "zondicons", "ant-design", "bx", "bxs", "gg", "cil", "lucide", "pixelarticons", "system-uicons", "ci", "akar-icons", "typcn", "radix-icons", "ep", "mdi-light", "fe", "eos-icons", "line-md", "charm", "prime", "heroicons-outline", "heroicons-solid", "uiw", "uim", "uit", "uis", "maki", "gridicons", "mi", "quill", "gala", "fluent", "icon-park-outline", "icon-park", "vscode-icons", "jam", "codicon", "pepicons", "bytesize", "ei", "fa6-solid", "fa6-regular", "octicon", "ooui", "nimbus", "openmoji", "twemoji", "noto", "noto-v1", "emojione", "emojione-monotone", "emojione-v1", "fxemoji", "bxl", "logos", "simple-icons", "cib", "fa6-brands", "arcticons", "file-icons", "brandico", "entypo-social", "cryptocurrency", "flag", "circle-flags", "flagpack", "cif", "gis", "map", "geo", "fad", "academicons", "wi", "healthicons", "medical-icon", "la", "eva", "dashicons", "flat-color-icons", "entypo", "foundation", "raphael", "icons8", "iwwa", "fa-solid", "fa-regular", "fa-brands", "fa", "fontisto", "icomoon-free", "ps", "subway", "oi", "wpf", "simple-line-icons", "et", "el", "vaadin", "grommet-icons", "whh", "si-glyph", "zmdi", "ls", "bpmn", "flat-ui", "vs", "topcoat", "il", "websymbol", "fontelico", "feather", "mono-icons"];
419
+ function createCDNLoader(cdnBase) {
420
+ const cache = /* @__PURE__ */ new Map();
421
+ function fetchCollection(name) {
422
+ if (!supportedCollection.includes(name))
423
+ return void 0;
424
+ if (!cache.has(name))
425
+ cache.set(name, $fetch(`${cdnBase}@iconify-json/${name}/icons.json`));
426
+ return cache.get(name);
427
+ }
428
+ return async (collection, icon, options) => {
429
+ let result = await loader.loadIcon(collection, icon, options);
430
+ if (result)
431
+ return result;
432
+ const iconSet = await fetchCollection(collection);
433
+ if (iconSet) {
434
+ const ids = [
435
+ icon,
436
+ icon.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
437
+ icon.replace(/([a-z])(\d+)/g, "$1-$2")
438
+ ];
439
+ result = await modern.searchForIcon(iconSet, collection, ids, options);
440
+ }
441
+ return result;
442
+ };
27
443
  }
444
+
445
+ const COLLECTION_NAME_PARTS_MAX = 3;
28
446
  const preset = (options = {}) => {
29
447
  const {
30
448
  scale = 1,
@@ -36,8 +454,46 @@ const preset = (options = {}) => {
36
454
  customizations = {},
37
455
  autoInstall = false,
38
456
  layer = "icons",
39
- unit
457
+ unit,
458
+ cdn
40
459
  } = options;
460
+ const loaderOptions = {
461
+ addXmlNs: true,
462
+ scale,
463
+ customCollections,
464
+ autoInstall,
465
+ warn: void 0,
466
+ customizations: {
467
+ ...customizations,
468
+ additionalProps: { ...extraProperties },
469
+ trimCustomSvg: true,
470
+ async iconCustomizer(collection, icon, props) {
471
+ await customizations.iconCustomizer?.(collection, icon, props);
472
+ if (unit) {
473
+ if (!props.width)
474
+ props.width = `${scale}${unit}`;
475
+ if (!props.height)
476
+ props.height = `${scale}${unit}`;
477
+ }
478
+ }
479
+ }
480
+ };
481
+ async function lookupIconLoader() {
482
+ if (cdn)
483
+ return createCDNLoader(cdn);
484
+ if (isNode && !isVSCode) {
485
+ try {
486
+ return await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
487
+ } catch {
488
+ }
489
+ try {
490
+ return require("@iconify/utils/lib/loader/node-loader.cjs");
491
+ } catch {
492
+ }
493
+ }
494
+ return utils.loadIcon;
495
+ }
496
+ let iconLoader;
41
497
  return {
42
498
  name: "@unocss/preset-icons",
43
499
  enforce: "pre",
@@ -51,38 +507,17 @@ const preset = (options = {}) => {
51
507
  let collection = "";
52
508
  let name = "";
53
509
  let svg;
54
- const iconLoader = await lookupIconLoader();
55
- const iconifyLoaderOptions = {
56
- addXmlNs: true,
57
- scale,
58
- customCollections,
59
- autoInstall,
60
- warn: void 0,
61
- customizations: {
62
- ...customizations,
63
- additionalProps: { ...extraProperties },
64
- trimCustomSvg: true,
65
- async iconCustomizer(collection2, icon, props) {
66
- await customizations.iconCustomizer?.(collection2, icon, props);
67
- if (unit) {
68
- if (!props.width)
69
- props.width = `${scale}${unit}`;
70
- if (!props.height)
71
- props.height = `${scale}${unit}`;
72
- }
73
- }
74
- },
75
- usedProps: {}
76
- };
510
+ iconLoader = iconLoader || await lookupIconLoader();
511
+ const usedProps = {};
77
512
  if (body.includes(":")) {
78
513
  [collection, name] = body.split(":");
79
- svg = await iconLoader(collection, name, iconifyLoaderOptions);
514
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
80
515
  } else {
81
516
  const parts = body.split(/-/g);
82
517
  for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
83
518
  collection = parts.slice(0, i).join("-");
84
519
  name = parts.slice(i).join("-");
85
- svg = await iconLoader(collection, name, iconifyLoaderOptions);
520
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
86
521
  if (svg)
87
522
  break;
88
523
  }
@@ -103,14 +538,14 @@ const preset = (options = {}) => {
103
538
  "-webkit-mask": "var(--un-icon) no-repeat",
104
539
  "-webkit-mask-size": "100% 100%",
105
540
  "background-color": "currentColor",
106
- ...iconifyLoaderOptions.usedProps
541
+ ...usedProps
107
542
  };
108
543
  } else {
109
544
  return {
110
545
  "background": `${url} no-repeat`,
111
546
  "background-size": "100% 100%",
112
547
  "background-color": "transparent",
113
- ...iconifyLoaderOptions.usedProps
548
+ ...usedProps
114
549
  };
115
550
  }
116
551
  },
package/dist/index.d.ts CHANGED
@@ -67,6 +67,14 @@ interface IconsOptions {
67
67
  * @default `em`
68
68
  */
69
69
  unit?: string;
70
+ /**
71
+ * Load icons from CDN. Should starts with `https://` and ends with `/`
72
+ *
73
+ * Recommends:
74
+ * - https://esm.sh/
75
+ * - https://cdn.skypack.dev/
76
+ */
77
+ cdn?: string;
70
78
  }
71
79
 
72
80
  declare const preset: (options?: IconsOptions) => Preset;
package/dist/index.mjs CHANGED
@@ -1,26 +1,444 @@
1
1
  import { warnOnce } from '@unocss/core';
2
- import { loadIcon } from '@iconify/utils';
2
+ import { loadIcon as loadIcon$1 } from '@iconify/utils';
3
3
  import { encodeSvgForCss } from '@iconify/utils/lib/svg/encode-svg-for-css';
4
+ import { loadIcon } from '@iconify/utils/lib/loader/loader';
5
+ import { searchForIcon } from '@iconify/utils/lib/loader/modern';
4
6
 
5
7
  const isNode = typeof process < "u" && typeof process.stdout < "u" && !process.versions.deno;
6
8
  const isVSCode = isNode && !!process.env.VSCODE_CWD;
7
9
 
8
- const COLLECTION_NAME_PARTS_MAX = 3;
9
- async function lookupIconLoader() {
10
- let useIconLoader;
11
- if (isNode && !isVSCode) {
12
- try {
13
- useIconLoader = await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
14
- } catch {
15
- try {
16
- useIconLoader = require("@iconify/utils/lib/loader/node-loader.cjs");
17
- } catch {
18
- useIconLoader = loadIcon;
10
+ const suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
11
+ const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
12
+ const JsonSigRx = /^["{[]|^-?[0-9][0-9.]{0,14}$/;
13
+ function jsonParseTransform(key, value) {
14
+ if (key === "__proto__" || key === "constructor") {
15
+ return;
16
+ }
17
+ return value;
18
+ }
19
+ function destr(val) {
20
+ if (typeof val !== "string") {
21
+ return val;
22
+ }
23
+ const _lval = val.toLowerCase();
24
+ if (_lval === "true") {
25
+ return true;
26
+ }
27
+ if (_lval === "false") {
28
+ return false;
29
+ }
30
+ if (_lval === "null") {
31
+ return null;
32
+ }
33
+ if (_lval === "nan") {
34
+ return NaN;
35
+ }
36
+ if (_lval === "infinity") {
37
+ return Infinity;
38
+ }
39
+ if (_lval === "undefined") {
40
+ return void 0;
41
+ }
42
+ if (!JsonSigRx.test(val)) {
43
+ return val;
44
+ }
45
+ try {
46
+ if (suspectProtoRx.test(val) || suspectConstructorRx.test(val)) {
47
+ return JSON.parse(val, jsonParseTransform);
48
+ }
49
+ return JSON.parse(val);
50
+ } catch (_e) {
51
+ return val;
52
+ }
53
+ }
54
+
55
+ const HASH_RE = /#/g;
56
+ const AMPERSAND_RE = /&/g;
57
+ const EQUAL_RE = /=/g;
58
+ const PLUS_RE = /\+/g;
59
+ const ENC_BRACKET_OPEN_RE = /%5B/gi;
60
+ const ENC_BRACKET_CLOSE_RE = /%5D/gi;
61
+ const ENC_CARET_RE = /%5E/gi;
62
+ const ENC_BACKTICK_RE = /%60/gi;
63
+ const ENC_CURLY_OPEN_RE = /%7B/gi;
64
+ const ENC_PIPE_RE = /%7C/gi;
65
+ const ENC_CURLY_CLOSE_RE = /%7D/gi;
66
+ const ENC_SPACE_RE = /%20/gi;
67
+ function encode(text) {
68
+ return encodeURI("" + text).replace(ENC_PIPE_RE, "|").replace(ENC_BRACKET_OPEN_RE, "[").replace(ENC_BRACKET_CLOSE_RE, "]");
69
+ }
70
+ function encodeQueryValue(text) {
71
+ return encode(text).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CURLY_OPEN_RE, "{").replace(ENC_CURLY_CLOSE_RE, "}").replace(ENC_CARET_RE, "^");
72
+ }
73
+ function encodeQueryKey(text) {
74
+ return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
75
+ }
76
+ function decode(text = "") {
77
+ try {
78
+ return decodeURIComponent("" + text);
79
+ } catch (_err) {
80
+ return "" + text;
81
+ }
82
+ }
83
+ function decodeQueryValue(text) {
84
+ return decode(text.replace(PLUS_RE, " "));
85
+ }
86
+
87
+ function parseQuery(paramsStr = "") {
88
+ const obj = {};
89
+ if (paramsStr[0] === "?") {
90
+ paramsStr = paramsStr.substr(1);
91
+ }
92
+ for (const param of paramsStr.split("&")) {
93
+ const s = param.match(/([^=]+)=?(.*)/) || [];
94
+ if (s.length < 2) {
95
+ continue;
96
+ }
97
+ const key = decode(s[1]);
98
+ if (key === "__proto__" || key === "constructor") {
99
+ continue;
100
+ }
101
+ const value = decodeQueryValue(s[2] || "");
102
+ if (obj[key]) {
103
+ if (Array.isArray(obj[key])) {
104
+ obj[key].push(value);
105
+ } else {
106
+ obj[key] = [obj[key], value];
107
+ }
108
+ } else {
109
+ obj[key] = value;
110
+ }
111
+ }
112
+ return obj;
113
+ }
114
+ function encodeQueryItem(key, val) {
115
+ if (typeof val === "number" || typeof val === "boolean") {
116
+ val = String(val);
117
+ }
118
+ if (!val) {
119
+ return encodeQueryKey(key);
120
+ }
121
+ if (Array.isArray(val)) {
122
+ return val.map((_val) => `${encodeQueryKey(key)}=${encodeQueryValue(_val)}`).join("&");
123
+ }
124
+ return `${encodeQueryKey(key)}=${encodeQueryValue(val)}`;
125
+ }
126
+ function stringifyQuery(query) {
127
+ return Object.keys(query).map((k) => encodeQueryItem(k, query[k])).join("&");
128
+ }
129
+ const PROTOCOL_REGEX = /^\w+:(\/\/)?/;
130
+ const PROTOCOL_RELATIVE_REGEX = /^\/\/[^/]+/;
131
+ function hasProtocol(inputStr, acceptProtocolRelative = false) {
132
+ return PROTOCOL_REGEX.test(inputStr) || acceptProtocolRelative && PROTOCOL_RELATIVE_REGEX.test(inputStr);
133
+ }
134
+ const TRAILING_SLASH_RE = /\/$|\/\?/;
135
+ function hasTrailingSlash(input = "", queryParams = false) {
136
+ if (!queryParams) {
137
+ return input.endsWith("/");
138
+ }
139
+ return TRAILING_SLASH_RE.test(input);
140
+ }
141
+ function withoutTrailingSlash(input = "", queryParams = false) {
142
+ if (!queryParams) {
143
+ return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
144
+ }
145
+ if (!hasTrailingSlash(input, true)) {
146
+ return input || "/";
147
+ }
148
+ const [s0, ...s] = input.split("?");
149
+ return (s0.slice(0, -1) || "/") + (s.length ? `?${s.join("?")}` : "");
150
+ }
151
+ function withTrailingSlash(input = "", queryParams = false) {
152
+ if (!queryParams) {
153
+ return input.endsWith("/") ? input : input + "/";
154
+ }
155
+ if (hasTrailingSlash(input, true)) {
156
+ return input || "/";
157
+ }
158
+ const [s0, ...s] = input.split("?");
159
+ return s0 + "/" + (s.length ? `?${s.join("?")}` : "");
160
+ }
161
+ function hasLeadingSlash(input = "") {
162
+ return input.startsWith("/");
163
+ }
164
+ function withoutLeadingSlash(input = "") {
165
+ return (hasLeadingSlash(input) ? input.substr(1) : input) || "/";
166
+ }
167
+ function withBase(input, base) {
168
+ if (isEmptyURL(base)) {
169
+ return input;
170
+ }
171
+ const _base = withoutTrailingSlash(base);
172
+ if (input.startsWith(_base)) {
173
+ return input;
174
+ }
175
+ return joinURL(_base, input);
176
+ }
177
+ function withQuery(input, query) {
178
+ const parsed = parseURL(input);
179
+ const mergedQuery = { ...parseQuery(parsed.search), ...query };
180
+ parsed.search = stringifyQuery(mergedQuery);
181
+ return stringifyParsedURL(parsed);
182
+ }
183
+ function isEmptyURL(url) {
184
+ return !url || url === "/";
185
+ }
186
+ function isNonEmptyURL(url) {
187
+ return url && url !== "/";
188
+ }
189
+ function joinURL(base, ...input) {
190
+ let url = base || "";
191
+ for (const i of input.filter(isNonEmptyURL)) {
192
+ url = url ? withTrailingSlash(url) + withoutLeadingSlash(i) : i;
193
+ }
194
+ return url;
195
+ }
196
+
197
+ function parseURL(input = "", defaultProto) {
198
+ if (!hasProtocol(input, true)) {
199
+ return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
200
+ }
201
+ const [protocol = "", auth, hostAndPath = ""] = (input.replace(/\\/g, "/").match(/([^:/]+:)?\/\/([^/@]+@)?(.*)/) || []).splice(1);
202
+ const [host = "", path = ""] = (hostAndPath.match(/([^/?#]*)(.*)?/) || []).splice(1);
203
+ const { pathname, search, hash } = parsePath(path);
204
+ return {
205
+ protocol,
206
+ auth: auth ? auth.substr(0, auth.length - 1) : "",
207
+ host,
208
+ pathname,
209
+ search,
210
+ hash
211
+ };
212
+ }
213
+ function parsePath(input = "") {
214
+ const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
215
+ return {
216
+ pathname,
217
+ search,
218
+ hash
219
+ };
220
+ }
221
+ function stringifyParsedURL(parsed) {
222
+ const fullpath = parsed.pathname + (parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "") + parsed.hash;
223
+ if (!parsed.protocol) {
224
+ return fullpath;
225
+ }
226
+ return parsed.protocol + "//" + (parsed.auth ? parsed.auth + "@" : "") + parsed.host + fullpath;
227
+ }
228
+
229
+ class FetchError extends Error {
230
+ constructor() {
231
+ super(...arguments);
232
+ this.name = "FetchError";
233
+ }
234
+ }
235
+ function createFetchError(request, error, response) {
236
+ let message = "";
237
+ if (request && response) {
238
+ message = `${response.status} ${response.statusText} (${request.toString()})`;
239
+ }
240
+ if (error) {
241
+ message = `${error.message} (${message})`;
242
+ }
243
+ const fetchError = new FetchError(message);
244
+ Object.defineProperty(fetchError, "request", { get() {
245
+ return request;
246
+ } });
247
+ Object.defineProperty(fetchError, "response", { get() {
248
+ return response;
249
+ } });
250
+ Object.defineProperty(fetchError, "data", { get() {
251
+ return response && response._data;
252
+ } });
253
+ return fetchError;
254
+ }
255
+
256
+ const payloadMethods = new Set(Object.freeze(["PATCH", "POST", "PUT", "DELETE"]));
257
+ function isPayloadMethod(method = "GET") {
258
+ return payloadMethods.has(method.toUpperCase());
259
+ }
260
+ function isJSONSerializable(val) {
261
+ if (val === void 0) {
262
+ return false;
263
+ }
264
+ const t = typeof val;
265
+ if (t === "string" || t === "number" || t === "boolean" || t === null) {
266
+ return true;
267
+ }
268
+ if (t !== "object") {
269
+ return false;
270
+ }
271
+ if (Array.isArray(val)) {
272
+ return true;
273
+ }
274
+ return val.constructor && val.constructor.name === "Object" || typeof val.toJSON === "function";
275
+ }
276
+ const textTypes = /* @__PURE__ */ new Set([
277
+ "image/svg",
278
+ "application/xml",
279
+ "application/xhtml",
280
+ "application/html"
281
+ ]);
282
+ const JSON_RE = /^application\/(?:[\w!#$%&*`\-.^~]*\+)?json(;.+)?$/i;
283
+ function detectResponseType(_contentType = "") {
284
+ if (!_contentType) {
285
+ return "json";
286
+ }
287
+ const contentType = _contentType.split(";").shift();
288
+ if (JSON_RE.test(contentType)) {
289
+ return "json";
290
+ }
291
+ if (textTypes.has(contentType) || contentType.startsWith("text/")) {
292
+ return "text";
293
+ }
294
+ return "blob";
295
+ }
296
+
297
+ const retryStatusCodes = /* @__PURE__ */ new Set([
298
+ 408,
299
+ 409,
300
+ 425,
301
+ 429,
302
+ 500,
303
+ 502,
304
+ 503,
305
+ 504
306
+ ]);
307
+ function createFetch(globalOptions) {
308
+ const { fetch, Headers } = globalOptions;
309
+ function onError(ctx) {
310
+ if (ctx.options.retry !== false) {
311
+ const retries = typeof ctx.options.retry === "number" ? ctx.options.retry : isPayloadMethod(ctx.options.method) ? 0 : 1;
312
+ const responseCode = ctx.response && ctx.response.status || 500;
313
+ if (retries > 0 && retryStatusCodes.has(responseCode)) {
314
+ return $fetchRaw(ctx.request, {
315
+ ...ctx.options,
316
+ retry: retries - 1
317
+ });
318
+ }
319
+ }
320
+ const err = createFetchError(ctx.request, ctx.error, ctx.response);
321
+ if (Error.captureStackTrace) {
322
+ Error.captureStackTrace(err, $fetchRaw);
323
+ }
324
+ throw err;
325
+ }
326
+ const $fetchRaw = async function $fetchRaw2(_request, _opts = {}) {
327
+ const ctx = {
328
+ request: _request,
329
+ options: { ...globalOptions.defaults, ..._opts },
330
+ response: void 0,
331
+ error: void 0
332
+ };
333
+ if (ctx.options.onRequest) {
334
+ await ctx.options.onRequest(ctx);
335
+ }
336
+ if (typeof ctx.request === "string") {
337
+ if (ctx.options.baseURL) {
338
+ ctx.request = withBase(ctx.request, ctx.options.baseURL);
339
+ }
340
+ if (ctx.options.params) {
341
+ ctx.request = withQuery(ctx.request, ctx.options.params);
342
+ }
343
+ if (ctx.options.body && isPayloadMethod(ctx.options.method)) {
344
+ if (isJSONSerializable(ctx.options.body)) {
345
+ ctx.options.body = JSON.stringify(ctx.options.body);
346
+ ctx.options.headers = new Headers(ctx.options.headers);
347
+ if (!ctx.options.headers.has("content-type")) {
348
+ ctx.options.headers.set("content-type", "application/json");
349
+ }
350
+ if (!ctx.options.headers.has("accept")) {
351
+ ctx.options.headers.set("accept", "application/json");
352
+ }
353
+ }
19
354
  }
20
355
  }
356
+ ctx.response = await fetch(ctx.request, ctx.options).catch(async (error) => {
357
+ ctx.error = error;
358
+ if (ctx.options.onRequestError) {
359
+ await ctx.options.onRequestError(ctx);
360
+ }
361
+ return onError(ctx);
362
+ });
363
+ const responseType = (ctx.options.parseResponse ? "json" : ctx.options.responseType) || detectResponseType(ctx.response.headers.get("content-type") || "");
364
+ if (responseType === "json") {
365
+ const data = await ctx.response.text();
366
+ const parseFn = ctx.options.parseResponse || destr;
367
+ ctx.response._data = parseFn(data);
368
+ } else {
369
+ ctx.response._data = await ctx.response[responseType]();
370
+ }
371
+ if (ctx.options.onResponse) {
372
+ await ctx.options.onResponse(ctx);
373
+ }
374
+ if (!ctx.response.ok) {
375
+ if (ctx.options.onResponseError) {
376
+ await ctx.options.onResponseError(ctx);
377
+ }
378
+ }
379
+ return ctx.response.ok ? ctx.response : onError(ctx);
380
+ };
381
+ const $fetch = function $fetch2(request, opts) {
382
+ return $fetchRaw(request, opts).then((r) => r._data);
383
+ };
384
+ $fetch.raw = $fetchRaw;
385
+ $fetch.create = (defaultOptions = {}) => createFetch({
386
+ ...globalOptions,
387
+ defaults: {
388
+ ...globalOptions.defaults,
389
+ ...defaultOptions
390
+ }
391
+ });
392
+ return $fetch;
393
+ }
394
+
395
+ const _globalThis = function() {
396
+ if (typeof globalThis !== "undefined") {
397
+ return globalThis;
398
+ }
399
+ if (typeof self !== "undefined") {
400
+ return self;
401
+ }
402
+ if (typeof window !== "undefined") {
403
+ return window;
21
404
  }
22
- return useIconLoader ?? loadIcon;
405
+ if (typeof global !== "undefined") {
406
+ return global;
407
+ }
408
+ throw new Error("unable to locate global object");
409
+ }();
410
+ const fetch = _globalThis.fetch || (() => Promise.reject(new Error("[ohmyfetch] global.fetch is not supported!")));
411
+ const Headers = _globalThis.Headers;
412
+ const $fetch = createFetch({ fetch, Headers });
413
+
414
+ const supportedCollection = ["material-symbols", "ic", "mdi", "ph", "ri", "carbon", "bi", "tabler", "ion", "uil", "teenyicons", "clarity", "iconoir", "majesticons", "zondicons", "ant-design", "bx", "bxs", "gg", "cil", "lucide", "pixelarticons", "system-uicons", "ci", "akar-icons", "typcn", "radix-icons", "ep", "mdi-light", "fe", "eos-icons", "line-md", "charm", "prime", "heroicons-outline", "heroicons-solid", "uiw", "uim", "uit", "uis", "maki", "gridicons", "mi", "quill", "gala", "fluent", "icon-park-outline", "icon-park", "vscode-icons", "jam", "codicon", "pepicons", "bytesize", "ei", "fa6-solid", "fa6-regular", "octicon", "ooui", "nimbus", "openmoji", "twemoji", "noto", "noto-v1", "emojione", "emojione-monotone", "emojione-v1", "fxemoji", "bxl", "logos", "simple-icons", "cib", "fa6-brands", "arcticons", "file-icons", "brandico", "entypo-social", "cryptocurrency", "flag", "circle-flags", "flagpack", "cif", "gis", "map", "geo", "fad", "academicons", "wi", "healthicons", "medical-icon", "la", "eva", "dashicons", "flat-color-icons", "entypo", "foundation", "raphael", "icons8", "iwwa", "fa-solid", "fa-regular", "fa-brands", "fa", "fontisto", "icomoon-free", "ps", "subway", "oi", "wpf", "simple-line-icons", "et", "el", "vaadin", "grommet-icons", "whh", "si-glyph", "zmdi", "ls", "bpmn", "flat-ui", "vs", "topcoat", "il", "websymbol", "fontelico", "feather", "mono-icons"];
415
+ function createCDNLoader(cdnBase) {
416
+ const cache = /* @__PURE__ */ new Map();
417
+ function fetchCollection(name) {
418
+ if (!supportedCollection.includes(name))
419
+ return void 0;
420
+ if (!cache.has(name))
421
+ cache.set(name, $fetch(`${cdnBase}@iconify-json/${name}/icons.json`));
422
+ return cache.get(name);
423
+ }
424
+ return async (collection, icon, options) => {
425
+ let result = await loadIcon(collection, icon, options);
426
+ if (result)
427
+ return result;
428
+ const iconSet = await fetchCollection(collection);
429
+ if (iconSet) {
430
+ const ids = [
431
+ icon,
432
+ icon.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
433
+ icon.replace(/([a-z])(\d+)/g, "$1-$2")
434
+ ];
435
+ result = await searchForIcon(iconSet, collection, ids, options);
436
+ }
437
+ return result;
438
+ };
23
439
  }
440
+
441
+ const COLLECTION_NAME_PARTS_MAX = 3;
24
442
  const preset = (options = {}) => {
25
443
  const {
26
444
  scale = 1,
@@ -32,8 +450,46 @@ const preset = (options = {}) => {
32
450
  customizations = {},
33
451
  autoInstall = false,
34
452
  layer = "icons",
35
- unit
453
+ unit,
454
+ cdn
36
455
  } = options;
456
+ const loaderOptions = {
457
+ addXmlNs: true,
458
+ scale,
459
+ customCollections,
460
+ autoInstall,
461
+ warn: void 0,
462
+ customizations: {
463
+ ...customizations,
464
+ additionalProps: { ...extraProperties },
465
+ trimCustomSvg: true,
466
+ async iconCustomizer(collection, icon, props) {
467
+ await customizations.iconCustomizer?.(collection, icon, props);
468
+ if (unit) {
469
+ if (!props.width)
470
+ props.width = `${scale}${unit}`;
471
+ if (!props.height)
472
+ props.height = `${scale}${unit}`;
473
+ }
474
+ }
475
+ }
476
+ };
477
+ async function lookupIconLoader() {
478
+ if (cdn)
479
+ return createCDNLoader(cdn);
480
+ if (isNode && !isVSCode) {
481
+ try {
482
+ return await import('@iconify/utils/lib/loader/node-loader').then((i) => i?.loadNodeIcon);
483
+ } catch {
484
+ }
485
+ try {
486
+ return require("@iconify/utils/lib/loader/node-loader.cjs");
487
+ } catch {
488
+ }
489
+ }
490
+ return loadIcon$1;
491
+ }
492
+ let iconLoader;
37
493
  return {
38
494
  name: "@unocss/preset-icons",
39
495
  enforce: "pre",
@@ -47,38 +503,17 @@ const preset = (options = {}) => {
47
503
  let collection = "";
48
504
  let name = "";
49
505
  let svg;
50
- const iconLoader = await lookupIconLoader();
51
- const iconifyLoaderOptions = {
52
- addXmlNs: true,
53
- scale,
54
- customCollections,
55
- autoInstall,
56
- warn: void 0,
57
- customizations: {
58
- ...customizations,
59
- additionalProps: { ...extraProperties },
60
- trimCustomSvg: true,
61
- async iconCustomizer(collection2, icon, props) {
62
- await customizations.iconCustomizer?.(collection2, icon, props);
63
- if (unit) {
64
- if (!props.width)
65
- props.width = `${scale}${unit}`;
66
- if (!props.height)
67
- props.height = `${scale}${unit}`;
68
- }
69
- }
70
- },
71
- usedProps: {}
72
- };
506
+ iconLoader = iconLoader || await lookupIconLoader();
507
+ const usedProps = {};
73
508
  if (body.includes(":")) {
74
509
  [collection, name] = body.split(":");
75
- svg = await iconLoader(collection, name, iconifyLoaderOptions);
510
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
76
511
  } else {
77
512
  const parts = body.split(/-/g);
78
513
  for (let i = COLLECTION_NAME_PARTS_MAX; i >= 1; i--) {
79
514
  collection = parts.slice(0, i).join("-");
80
515
  name = parts.slice(i).join("-");
81
- svg = await iconLoader(collection, name, iconifyLoaderOptions);
516
+ svg = await iconLoader(collection, name, { ...loaderOptions, usedProps });
82
517
  if (svg)
83
518
  break;
84
519
  }
@@ -99,14 +534,14 @@ const preset = (options = {}) => {
99
534
  "-webkit-mask": "var(--un-icon) no-repeat",
100
535
  "-webkit-mask-size": "100% 100%",
101
536
  "background-color": "currentColor",
102
- ...iconifyLoaderOptions.usedProps
537
+ ...usedProps
103
538
  };
104
539
  } else {
105
540
  return {
106
541
  "background": `${url} no-repeat`,
107
542
  "background-size": "100% 100%",
108
543
  "background-color": "transparent",
109
- ...iconifyLoaderOptions.usedProps
544
+ ...usedProps
110
545
  };
111
546
  }
112
547
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unocss/preset-icons",
3
- "version": "0.32.8",
3
+ "version": "0.32.12",
4
4
  "description": "Pure CSS Icons for UnoCSS",
5
5
  "keywords": [
6
6
  "unocss",
@@ -38,10 +38,11 @@
38
38
  "sideEffects": false,
39
39
  "dependencies": {
40
40
  "@iconify/utils": "^1.0.32",
41
- "@unocss/core": "0.32.8"
41
+ "@unocss/core": "0.32.12"
42
42
  },
43
43
  "devDependencies": {
44
- "@iconify/types": "^1.1.0"
44
+ "@iconify/types": "^1.1.0",
45
+ "ohmyfetch": "^0.4.16"
45
46
  },
46
47
  "scripts": {
47
48
  "build": "unbuild",