@dubium/icons 0.0.2-alpha.2 → 0.0.2-alpha.4
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 +286 -49
- package/dist/collection/AdjustmentsPlusIcon.d.ts +3 -0
- package/dist/collection/{Icon123Icon.js → AdjustmentsPlusIcon.js} +3 -3
- package/dist/collection/AdjustmentsQuestionIcon.d.ts +3 -0
- package/dist/collection/AdjustmentsQuestionIcon.js +18 -0
- package/dist/collection/AlarmPlusFilledIcon.d.ts +3 -0
- package/dist/collection/AlarmPlusFilledIcon.js +29 -0
- package/dist/collection/AlarmSnoozeFilledIcon.d.ts +3 -0
- package/dist/collection/AlarmSnoozeFilledIcon.js +29 -0
- package/dist/collection/{Icon24HoursIcon.d.ts → AlarmSnoozeIcon.d.ts} +2 -2
- package/dist/collection/{Icon360Icon.js → AlarmSnoozeIcon.js} +3 -3
- package/dist/collection/AlbumIcon.d.ts +3 -0
- package/dist/collection/{Icon24HoursIcon.js → AlbumIcon.js} +3 -3
- package/dist/collection/AlbumOffIcon.d.ts +3 -0
- package/dist/collection/AlbumOffIcon.js +18 -0
- package/dist/collection/AlertCircleFilledIcon.d.ts +3 -0
- package/dist/collection/AlertCircleFilledIcon.js +15 -0
- package/dist/collection/{Icon360ViewIcon.d.ts → AlertCircleIcon.d.ts} +2 -2
- package/dist/collection/{Icon2faIcon.js → AlertCircleIcon.js} +3 -3
- package/dist/collection/AlertHexagonIcon.d.ts +3 -0
- package/dist/collection/AlertHexagonIcon.js +18 -0
- package/dist/collection/AlignBoxBottomRightFilledIcon.d.ts +3 -0
- package/dist/collection/AlignBoxBottomRightFilledIcon.js +15 -0
- package/dist/collection/AlignBoxBottomRightIcon.d.ts +3 -0
- package/dist/collection/AlignBoxBottomRightIcon.js +18 -0
- package/dist/collection/AlignBoxCenterMiddleFilledIcon.d.ts +3 -0
- package/dist/collection/AlignBoxCenterMiddleFilledIcon.js +15 -0
- package/dist/collection/AlignBoxCenterMiddleIcon.d.ts +3 -0
- package/dist/collection/AlignBoxCenterMiddleIcon.js +18 -0
- package/dist/collection/AlignBoxLeftBottomFilledIcon.d.ts +3 -0
- package/dist/collection/AlignBoxLeftBottomFilledIcon.js +15 -0
- package/dist/collection/AlignBoxLeftBottomIcon.d.ts +3 -0
- package/dist/collection/AlignBoxLeftBottomIcon.js +18 -0
- package/dist/collection/AlignBoxLeftMiddleFilledIcon.d.ts +3 -0
- package/dist/collection/AlignBoxLeftMiddleFilledIcon.js +15 -0
- package/dist/collection/AlignBoxLeftMiddleIcon.d.ts +3 -0
- package/dist/collection/AlignBoxLeftMiddleIcon.js +18 -0
- package/dist/collection/index.d.ts +20 -7
- package/dist/collection/index.js +19 -6
- package/dist/collection/types.d.ts +17 -1
- package/dist/icon/Icon.container.d.ts +29 -0
- package/dist/icon/Icon.container.js +19 -0
- package/dist/icon/Icon.d.ts +5 -0
- package/dist/icon/Icon.js +20 -0
- package/dist/icon/Icon.types.d.ts +59 -0
- package/dist/icon/index.d.ts +13 -0
- package/dist/icon/index.js +2 -0
- package/dist/vite/icon/Icon.create.d.ts +35 -0
- package/dist/{spa → vite}/icon/Icon.create.js +1 -1
- package/dist/vite/icon/Icon.d.ts +66 -0
- package/dist/vite/icon/Icon.js +79 -0
- package/dist/vite/icon/Icon.types.d.ts +88 -0
- package/dist/vite/icon/index.d.ts +6 -0
- package/dist/vite/index.d.ts +10 -46
- package/dist/vite/index.js +6 -166
- package/dist/vite/plugin/index.d.ts +11 -0
- package/dist/vite/plugin/index.js +2 -0
- package/dist/vite/plugin/plugin.d.ts +41 -0
- package/dist/vite/plugin/plugin.js +105 -0
- package/dist/vite/plugin/plugin.types.d.ts +99 -0
- package/dist/vite/plugin/scanner/index.d.ts +9 -0
- package/dist/vite/plugin/scanner/scanner.imports.d.ts +5 -0
- package/dist/vite/plugin/scanner/scanner.imports.js +36 -0
- package/dist/vite/plugin/scanner/scanner.jsx.d.ts +24 -0
- package/dist/vite/plugin/scanner/scanner.jsx.js +58 -0
- package/dist/vite/plugin/scanner/scanner.lexical.d.ts +30 -0
- package/dist/vite/plugin/scanner/scanner.lexical.js +140 -0
- package/dist/vite/plugin/scanner/scanner.properties.d.ts +9 -0
- package/dist/vite/plugin/scanner/scanner.properties.js +78 -0
- package/dist/vite/plugin/scanner/scanner.regex.d.ts +21 -0
- package/dist/vite/plugin/scanner/scanner.regex.js +24 -0
- package/dist/vite/plugin/scanner/scanner.source.d.ts +18 -0
- package/dist/vite/plugin/scanner/scanner.source.js +23 -0
- package/dist/vite/plugin/scanner/scanner.types.d.ts +1 -0
- package/dist/vite/plugin/sources/index.d.ts +11 -0
- package/dist/vite/plugin/sources/sources.catalog.d.ts +17 -0
- package/dist/vite/plugin/sources/sources.catalog.js +19 -0
- package/dist/vite/plugin/sources/sources.files.d.ts +34 -0
- package/dist/vite/plugin/sources/sources.files.js +43 -0
- package/dist/vite/plugin/sources/sources.types.d.ts +1 -0
- package/dist/vite/plugin/sources/sources.validate.d.ts +13 -0
- package/dist/vite/plugin/sources/sources.validate.js +12 -0
- package/dist/vite/plugin/virtual/index.d.ts +9 -0
- package/dist/vite/plugin/virtual/virtual.constants.d.ts +15 -0
- package/dist/vite/plugin/virtual/virtual.constants.js +4 -0
- package/dist/vite/plugin/virtual/virtual.module.d.ts +23 -0
- package/dist/vite/plugin/virtual/virtual.module.js +27 -0
- package/dist/vite/provider/IconProvider.context.d.ts +14 -0
- package/dist/vite/provider/IconProvider.context.js +5 -0
- package/dist/{spa → vite}/provider/IconProvider.d.ts +3 -2
- package/dist/{spa → vite}/provider/IconProvider.js +1 -1
- package/dist/{spa → vite}/provider/index.d.ts +2 -2
- package/dist/{spa/provider/IconProvider.context.d.ts → vite/provider/useIconContext.d.ts} +4 -14
- package/dist/vite/provider/useIconContext.js +6 -0
- package/dist/vite/runtime/IconRuntime.registry.d.ts +54 -0
- package/dist/vite/runtime/IconRuntime.registry.js +58 -0
- package/dist/vite/runtime/index.d.ts +9 -0
- package/package.json +17 -17
- package/dist/_virtual/__vite-browser-external.js +0 -8
- package/dist/_virtual/_rolldown/runtime.js +0 -4
- package/dist/collection/Icon123Icon.d.ts +0 -3
- package/dist/collection/Icon2faIcon.d.ts +0 -3
- package/dist/collection/Icon360Icon.d.ts +0 -3
- package/dist/collection/Icon360ViewIcon.js +0 -18
- package/dist/spa/icon/Icon.create.d.ts +0 -40
- package/dist/spa/icon/Icon.d.ts +0 -25
- package/dist/spa/icon/Icon.js +0 -58
- package/dist/spa/icon/Icon.registry.d.ts +0 -12
- package/dist/spa/icon/Icon.types.d.ts +0 -71
- package/dist/spa/icon/index.d.ts +0 -9
- package/dist/spa/index.d.ts +0 -8
- package/dist/spa/index.js +0 -5
- package/dist/spa/provider/IconProvider.context.js +0 -5
- package/dist/ssr/icon/Icon.container.d.ts +0 -26
- package/dist/ssr/icon/Icon.container.js +0 -23
- package/dist/ssr/icon/Icon.create.d.ts +0 -35
- package/dist/ssr/icon/Icon.create.js +0 -8
- package/dist/ssr/icon/Icon.d.ts +0 -6
- package/dist/ssr/icon/Icon.js +0 -27
- package/dist/ssr/icon/Icon.registry.d.ts +0 -12
- package/dist/ssr/icon/Icon.registry.js +0 -10
- package/dist/ssr/icon/Icon.types.d.ts +0 -97
- package/dist/ssr/icon/index.d.ts +0 -10
- package/dist/ssr/index.d.ts +0 -6
- package/dist/ssr/index.js +0 -4
- /package/dist/{spa → vite}/provider/IconProvider.types.d.ts +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
import type { IIconComponentProps } from "../../collection/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Тип пустого реестра иконок.
|
|
5
|
+
*
|
|
6
|
+
* Используется как default generic, чтобы keyof реестра
|
|
7
|
+
* не превращался в обычный string.
|
|
8
|
+
*/
|
|
9
|
+
export type TEmptyIconRegistry = Readonly<Record<never, never>>;
|
|
10
|
+
/**
|
|
11
|
+
* React-компонент иконки.
|
|
12
|
+
*/
|
|
13
|
+
export type TIcon = ComponentType<IIconComponentProps>;
|
|
14
|
+
/**
|
|
15
|
+
* Модуль динамически загружаемой иконки.
|
|
16
|
+
*/
|
|
17
|
+
export type TIconModule = {
|
|
18
|
+
default: TIcon;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Lazy loader иконки.
|
|
22
|
+
*/
|
|
23
|
+
export type TIconLoader = () => Promise<TIconModule>;
|
|
24
|
+
/**
|
|
25
|
+
* Runtime / custom registry иконок.
|
|
26
|
+
*
|
|
27
|
+
* В runtime ключом может быть любая строка.
|
|
28
|
+
*/
|
|
29
|
+
export type TIconRegistry = Readonly<Record<string, TIconLoader>>;
|
|
30
|
+
/**
|
|
31
|
+
* Все runtime-экспорты collection/index.ts.
|
|
32
|
+
*
|
|
33
|
+
* Например:
|
|
34
|
+
*
|
|
35
|
+
* "AB2Icon"
|
|
36
|
+
* "AbacusIcon"
|
|
37
|
+
* "AccessibleIcon"
|
|
38
|
+
*/
|
|
39
|
+
type TCollectionExportName = Extract<keyof typeof import("../../collection/index.js"), string>;
|
|
40
|
+
/**
|
|
41
|
+
* Удаляет суффикс "Icon".
|
|
42
|
+
*
|
|
43
|
+
* Например:
|
|
44
|
+
*
|
|
45
|
+
* "AbacusIcon" -> "Abacus"
|
|
46
|
+
* "AccessibleIcon" -> "Accessible"
|
|
47
|
+
*/
|
|
48
|
+
type TRemoveIconSuffix<TName extends string> = TName extends `${infer TIconName}Icon` ? TIconName : never;
|
|
49
|
+
/**
|
|
50
|
+
* Все имена встроенных иконок пакета.
|
|
51
|
+
*
|
|
52
|
+
* Автоматически вычисляется из:
|
|
53
|
+
*
|
|
54
|
+
* src/icons/collection/index.ts
|
|
55
|
+
*
|
|
56
|
+
* Поэтому после sync:icons список обновляется автоматически.
|
|
57
|
+
*/
|
|
58
|
+
export type TPackageIconName = TRemoveIconSuffix<TCollectionExportName>;
|
|
59
|
+
/**
|
|
60
|
+
* Допустимое имя иконки.
|
|
61
|
+
*
|
|
62
|
+
* Включает:
|
|
63
|
+
*
|
|
64
|
+
* 1. все встроенные иконки @sg/icons;
|
|
65
|
+
* 2. ключи кастомного registry, если он передан.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* type TName = TIconName
|
|
71
|
+
*
|
|
72
|
+
* // "AB2" | "Abacus" | "Accessible" | ...
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* const customIcons = {
|
|
79
|
+
* CompanyLogo: () => import("./CompanyLogoIcon"),
|
|
80
|
+
* } as const
|
|
81
|
+
*
|
|
82
|
+
* type TName = TIconName<typeof customIcons>
|
|
83
|
+
*
|
|
84
|
+
* // package icons | "CompanyLogo"
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export type TIconName<TCustomIcons extends TIconRegistry = TEmptyIconRegistry> = TPackageIconName | Extract<keyof TCustomIcons, string>;
|
|
88
|
+
export type { IIconComponentProps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Публичный API Vite Icon.
|
|
3
|
+
*/
|
|
4
|
+
export { Icon, type IconProps } from "./Icon.js";
|
|
5
|
+
export { createIcon } from "./Icon.create.js";
|
|
6
|
+
export type { IIconComponentProps, TEmptyIconRegistry, TIcon, TIconLoader, TIconModule, TIconName, TIconRegistry, TPackageIconName, } from "./Icon.types.js";
|
package/dist/vite/index.d.ts
CHANGED
|
@@ -1,50 +1,14 @@
|
|
|
1
|
-
import type { Plugin } from "vite";
|
|
2
|
-
export interface DubiumIconsPluginOptions {
|
|
3
|
-
/**
|
|
4
|
-
* Имена компонентов, которые плагин должен анализировать.
|
|
5
|
-
*
|
|
6
|
-
* @default ["Icon"]
|
|
7
|
-
*/
|
|
8
|
-
componentNames?: readonly string[];
|
|
9
|
-
/**
|
|
10
|
-
* Иконки, которые необходимо включить вручную.
|
|
11
|
-
*
|
|
12
|
-
* Используется для runtime-имён:
|
|
13
|
-
* `<Icon name={valueFromApi} />`.
|
|
14
|
-
*/
|
|
15
|
-
include?: readonly string[];
|
|
16
|
-
/**
|
|
17
|
-
* Имя npm-пакета с иконками.
|
|
18
|
-
*
|
|
19
|
-
* @default "@dubium/icons"
|
|
20
|
-
*/
|
|
21
|
-
packageName?: string;
|
|
22
|
-
/**
|
|
23
|
-
* Каталоги приложения, которые нужно сканировать.
|
|
24
|
-
* Пути могут быть абсолютными или относительными к Vite root.
|
|
25
|
-
*
|
|
26
|
-
* @default ["src"]
|
|
27
|
-
*/
|
|
28
|
-
scan?: readonly string[];
|
|
29
|
-
/**
|
|
30
|
-
* Если true, сборка завершится ошибкой при обнаружении
|
|
31
|
-
* `<Icon name={dynamicValue} />`.
|
|
32
|
-
*
|
|
33
|
-
* При false будет выведено предупреждение.
|
|
34
|
-
*
|
|
35
|
-
* @default false
|
|
36
|
-
*/
|
|
37
|
-
strictDynamicNames?: boolean;
|
|
38
|
-
}
|
|
39
1
|
/**
|
|
40
|
-
*
|
|
2
|
+
* Публичный API иконок для Vite.
|
|
41
3
|
*
|
|
42
|
-
*
|
|
43
|
-
* `<Icon name="User" />`,
|
|
44
|
-
* а затем создаёт virtual registry только для найденных имён.
|
|
4
|
+
* Источники иконок:
|
|
45
5
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
6
|
+
* 1. IconProvider;
|
|
7
|
+
* 2. runtime registry;
|
|
8
|
+
* 3. compile-time virtual registry.
|
|
48
9
|
*/
|
|
49
|
-
export
|
|
50
|
-
export
|
|
10
|
+
export { createIcon, Icon, type IconProps } from "./icon/index.js";
|
|
11
|
+
export { IconProvider, useIconContext } from "./provider/index.js";
|
|
12
|
+
export { getRuntimeIconLoader, getRuntimeIconsVersion, registerIcons, removeIconOwner, subscribeRuntimeIcons, } from "./runtime/index.js";
|
|
13
|
+
export type { IIconComponentProps, TEmptyIconRegistry, TIcon, TIconLoader, TIconModule, TIconName, TIconRegistry, TPackageIconName, } from "./icon/index.js";
|
|
14
|
+
export type { IIconContextValue, IIconProviderProps } from "./provider/index.js";
|
package/dist/vite/index.js
CHANGED
|
@@ -1,166 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
".cjs",
|
|
8
|
-
".ts",
|
|
9
|
-
".tsx"
|
|
10
|
-
]), a = /* @__PURE__ */ new Set([
|
|
11
|
-
".git",
|
|
12
|
-
".next",
|
|
13
|
-
".nuxt",
|
|
14
|
-
".output",
|
|
15
|
-
".turbo",
|
|
16
|
-
"build",
|
|
17
|
-
"coverage",
|
|
18
|
-
"dist",
|
|
19
|
-
"node_modules"
|
|
20
|
-
]), o = (e) => e.replaceAll("\\", "/"), s = (e, t) => {
|
|
21
|
-
if (e.size !== t.size) return !1;
|
|
22
|
-
for (let n of e) if (!t.has(n)) return !1;
|
|
23
|
-
return !0;
|
|
24
|
-
}, c = (e) => {
|
|
25
|
-
let t = e.map((e) => e.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"));
|
|
26
|
-
return RegExp(`<\\s*(?:${t.join("|")})\\b`, "gu");
|
|
27
|
-
}, l = (e, t) => {
|
|
28
|
-
let n = null, r = !1, i = 0;
|
|
29
|
-
for (let a = t; a < e.length; a += 1) {
|
|
30
|
-
let t = e[a];
|
|
31
|
-
if (n) {
|
|
32
|
-
if (r) {
|
|
33
|
-
r = !1;
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (t === "\\") {
|
|
37
|
-
r = !0;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
t === n && (n = null);
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
if (t === "'" || t === "\"" || t === "`") {
|
|
44
|
-
n = t;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (t === "{") {
|
|
48
|
-
i += 1;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (t === "}") {
|
|
52
|
-
i = Math.max(0, i - 1);
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
if (t === ">" && i === 0) return a;
|
|
56
|
-
}
|
|
57
|
-
return -1;
|
|
58
|
-
}, u = (e) => {
|
|
59
|
-
let t = /\bname\s*=\s*(["'])(.*?)\1/su.exec(e);
|
|
60
|
-
if (t) return t[2].trim();
|
|
61
|
-
let n = /\bname\s*=\s*\{\s*(?:(["'])(.*?)\1|`([^`${}]*)`)\s*\}/su.exec(e);
|
|
62
|
-
return n ? (n[2] ?? n[3] ?? "").trim() : null;
|
|
63
|
-
}, d = (e) => /\bname\s*=/u.test(e), f = (e, t) => {
|
|
64
|
-
let n = /* @__PURE__ */ new Set(), r = c(t), i = 0;
|
|
65
|
-
for (let t of e.matchAll(r)) {
|
|
66
|
-
let r = t.index ?? 0, a = l(e, r);
|
|
67
|
-
if (a === -1) continue;
|
|
68
|
-
let o = e.slice(r, a + 1), s = u(o);
|
|
69
|
-
if (s) {
|
|
70
|
-
n.add(s);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
d(o) && (i += 1);
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
dynamicNames: i,
|
|
77
|
-
icons: n
|
|
78
|
-
};
|
|
79
|
-
}, p = async (e) => {
|
|
80
|
-
let n;
|
|
81
|
-
try {
|
|
82
|
-
n = await (0, t.readdir)(e, { withFileTypes: !0 });
|
|
83
|
-
} catch {
|
|
84
|
-
return [];
|
|
85
|
-
}
|
|
86
|
-
let r = [];
|
|
87
|
-
for (let o of n) {
|
|
88
|
-
let n = (0, t.join)(e, o.name);
|
|
89
|
-
if (o.isDirectory()) {
|
|
90
|
-
a.has(o.name) || r.push(...await p(n));
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
o.isFile() && i.has((0, t.extname)(o.name).toLowerCase()) && r.push(n);
|
|
94
|
-
}
|
|
95
|
-
return r;
|
|
96
|
-
}, m = (e, t) => `/**
|
|
97
|
-
* AUTO-GENERATED in memory by @dubium/icons/vite.
|
|
98
|
-
* Contains only icons used by the current application.
|
|
99
|
-
*/
|
|
100
|
-
export const iconRegistry = {
|
|
101
|
-
${e.map((e) => `\t${JSON.stringify(e)}: () => import(${JSON.stringify(`${t}/icons/${e}`)}),`).join("\n")}
|
|
102
|
-
}
|
|
103
|
-
`, h = (e = {}) => {
|
|
104
|
-
let a = e.componentNames?.length ? [...e.componentNames] : ["Icon"], c = e.packageName ?? "@dubium/icons", l = e.scan?.length ? [...e.scan] : ["src"], u = new Set(e.include ?? []), d = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), g = process.cwd(), _, v = () => {
|
|
105
|
-
let e = new Set(u);
|
|
106
|
-
for (let t of d.values()) for (let n of t) e.add(n);
|
|
107
|
-
return [...e].sort((e, t) => e.localeCompare(t));
|
|
108
|
-
}, y = async (e) => {
|
|
109
|
-
let n = o(e);
|
|
110
|
-
if (!i.has((0, t.extname)(e).toLowerCase())) return d.delete(n), h.delete(n), !1;
|
|
111
|
-
let r;
|
|
112
|
-
try {
|
|
113
|
-
r = await (0, t.readFile)(e, "utf8");
|
|
114
|
-
} catch {
|
|
115
|
-
let e = d.delete(n), t = h.delete(n);
|
|
116
|
-
return e || t;
|
|
117
|
-
}
|
|
118
|
-
let c = d.get(n) ?? /* @__PURE__ */ new Set(), l = h.get(n) ?? 0, u = f(r, a);
|
|
119
|
-
return d.set(n, u.icons), u.dynamicNames > 0 ? h.set(n, u.dynamicNames) : h.delete(n), !s(c, u.icons) || l !== u.dynamicNames;
|
|
120
|
-
}, b = async (e) => {
|
|
121
|
-
d.clear(), h.clear();
|
|
122
|
-
for (let n of l) {
|
|
123
|
-
let r = await p((0, t.isAbsolute)(n) ? n : (0, t.resolve)(g, n));
|
|
124
|
-
for (let t of r) e?.addWatchFile(t), await y(t);
|
|
125
|
-
}
|
|
126
|
-
}, x = () => h.size === 0 ? null : `[@dubium/icons] Найдены динамические name у <Icon>:\n${[...h.entries()].map(([e, n]) => ` - ${o((0, t.relative)(g, e))}: ${n}`).join("\n")}\nVite не может определить такие иконки на этапе сборки. Добавьте допустимые имена в dubiumIcons({ include: [...] }).`, S = () => {
|
|
127
|
-
if (!_) return;
|
|
128
|
-
let e = _.moduleGraph.getModuleById(r);
|
|
129
|
-
e && _.moduleGraph.invalidateModule(e), _.ws.send({ type: "full-reload" });
|
|
130
|
-
};
|
|
131
|
-
return {
|
|
132
|
-
name: "dubium-icons",
|
|
133
|
-
enforce: "pre",
|
|
134
|
-
configResolved(e) {
|
|
135
|
-
g = e.root;
|
|
136
|
-
},
|
|
137
|
-
async buildStart() {
|
|
138
|
-
await b(this);
|
|
139
|
-
let t = x();
|
|
140
|
-
t && (e.strictDynamicNames ? this.error(t) : this.warn(t));
|
|
141
|
-
},
|
|
142
|
-
configureServer(e) {
|
|
143
|
-
_ = e;
|
|
144
|
-
let t = async (e) => {
|
|
145
|
-
await y(e) && S();
|
|
146
|
-
}, n = async (e) => {
|
|
147
|
-
let t = o(e);
|
|
148
|
-
(d.delete(t) || h.delete(t)) && S();
|
|
149
|
-
};
|
|
150
|
-
return e.watcher.on("add", t), e.watcher.on("unlink", n), () => {
|
|
151
|
-
e.watcher.off("add", t), e.watcher.off("unlink", n);
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
resolveId(e) {
|
|
155
|
-
return e === n ? r : null;
|
|
156
|
-
},
|
|
157
|
-
load(e) {
|
|
158
|
-
return e === r ? m(v(), c) : null;
|
|
159
|
-
},
|
|
160
|
-
async handleHotUpdate(e) {
|
|
161
|
-
if (await y(e.file)) return S(), [];
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
//#endregion
|
|
166
|
-
export { h as default, h as dubiumIcons };
|
|
1
|
+
import { IconProvider as e } from "./provider/IconProvider.js";
|
|
2
|
+
import { useIconContext as t } from "./provider/useIconContext.js";
|
|
3
|
+
import { getRuntimeIconLoader as n, getRuntimeIconsVersion as r, registerIcons as i, removeIconOwner as a, subscribeRuntimeIcons as o } from "./runtime/IconRuntime.registry.js";
|
|
4
|
+
import { Icon as s } from "./icon/Icon.js";
|
|
5
|
+
import { createIcon as c } from "./icon/Icon.create.js";
|
|
6
|
+
export { s as Icon, e as IconProvider, c as createIcon, n as getRuntimeIconLoader, r as getRuntimeIconsVersion, i as registerIcons, a as removeIconOwner, o as subscribeRuntimeIcons, t as useIconContext };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Публичный API Vite-плагина {@link dubiumIcons}.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Плагин сканирует исходники приложения, строит виртуальный модуль
|
|
6
|
+
* `virtual:@dubium/icons-registry` с реестром только реально используемых
|
|
7
|
+
* иконок и разрешает его через `resolveId`/`load`.
|
|
8
|
+
*/
|
|
9
|
+
export { dubiumIcons } from "./plugin.js";
|
|
10
|
+
export { dubiumIcons as default } from "./plugin.js";
|
|
11
|
+
export type { DubiumIconsPluginOptions, TDubiumIconSource } from "./plugin.types.js";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import type { DubiumIconsPluginOptions } from "./plugin.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Плагин Vite для автоматического обнаружения иконок `@dubium/icons`.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Плагин сканирует исходники проекта, находит статические использования
|
|
8
|
+
* Vite-компонента `Icon` (в виде JSX-тегов и строковых конфигураций) и генерирует
|
|
9
|
+
* виртуальный модуль `virtual:@dubium/icons-registry` с ленивыми загрузчиками
|
|
10
|
+
* только для используемых иконок.
|
|
11
|
+
*
|
|
12
|
+
* По умолчанию компонентом считается любой JSX-тег `<Icon>`, имя которого
|
|
13
|
+
* импортировано из `@dubium/icons/vite`. Набор имён можно переопределить через
|
|
14
|
+
* `options.componentNames`, а список свойств, значения которых трактуются как имена
|
|
15
|
+
* иконок, — через `options.propertyNames`. Теги прочих компонентов, например
|
|
16
|
+
* `<IconButton>`, игнорируются.
|
|
17
|
+
*
|
|
18
|
+
* Сканируются все файлы директории `src` (настраивается через `options.scan`).
|
|
19
|
+
* Источником иконок по умолчанию является пакет `@dubium/icons` с подстановкой
|
|
20
|
+
* имени в `importPattern`; локальные каталоги SVG-файлов подключаются через
|
|
21
|
+
* `options.sources`.
|
|
22
|
+
*
|
|
23
|
+
* Динамические имена вида `<Icon name={expression}>` не могут быть разрешены
|
|
24
|
+
* на этапе сборки — о них выводится предупреждение с указанием файлов.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Опции плагина
|
|
27
|
+
* @returns Объект плагина Vite
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* // vite.config.ts
|
|
33
|
+
* import { defineConfig } from "vite"
|
|
34
|
+
* import { dubiumIcons } from "@dubium/icons/vite/plugin"
|
|
35
|
+
*
|
|
36
|
+
* export default defineConfig({
|
|
37
|
+
* plugins: [dubiumIcons()],
|
|
38
|
+
* })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare const dubiumIcons: (options?: DubiumIconsPluginOptions) => Plugin;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { scanSource as e } from "./scanner/scanner.source.js";
|
|
2
|
+
import { DEFAULT_EXTENSIONS as t, getSourceFiles as n, isPathInsideDirectory as r, normalizePath as i } from "./sources/sources.files.js";
|
|
3
|
+
import { buildLocalCatalog as a } from "./sources/sources.catalog.js";
|
|
4
|
+
import { validateSources as o } from "./sources/sources.validate.js";
|
|
5
|
+
import { RESOLVED_VIRTUAL_MODULE_ID as s } from "./virtual/virtual.constants.js";
|
|
6
|
+
import { createVirtualModuleSource as c } from "./virtual/virtual.module.js";
|
|
7
|
+
import { readFile as l } from "node:fs/promises";
|
|
8
|
+
import { extname as u, relative as d, resolve as f } from "node:path";
|
|
9
|
+
//#region src/icons/vite/plugin/plugin.ts
|
|
10
|
+
var p = (e, t) => {
|
|
11
|
+
if (e.size !== t.size) return !1;
|
|
12
|
+
for (let n of e) if (!t.has(n)) return !1;
|
|
13
|
+
return !0;
|
|
14
|
+
}, m = (m = {}) => {
|
|
15
|
+
let h = m.componentNames ? [...m.componentNames] : [], g = m.propertyNames ? [...m.propertyNames] : [], _ = m.scan ? [...m.scan] : ["src"], v = m.sources ? [...m.sources] : [{
|
|
16
|
+
type: "package",
|
|
17
|
+
importPattern: "@dubium/icons/icons/{name}"
|
|
18
|
+
}];
|
|
19
|
+
o(v);
|
|
20
|
+
let y = v.filter((e) => e.type === "local"), b = v.find((e) => e.type === "package"), x = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Map(), C = [], w = process.cwd(), T, E = "", D = () => {
|
|
21
|
+
let e = /* @__PURE__ */ new Set();
|
|
22
|
+
for (let t of x.values()) for (let n of t) e.add(n);
|
|
23
|
+
return [...e].sort((e, t) => e.localeCompare(t));
|
|
24
|
+
}, O = async (n, r) => {
|
|
25
|
+
let a = i(n);
|
|
26
|
+
if (!t.has(u(n).toLowerCase())) {
|
|
27
|
+
let e = x.delete(a), t = S.delete(a);
|
|
28
|
+
return e || t;
|
|
29
|
+
}
|
|
30
|
+
let o;
|
|
31
|
+
try {
|
|
32
|
+
o = r ? await r() : await l(n, "utf8");
|
|
33
|
+
} catch {
|
|
34
|
+
let e = x.delete(a), t = S.delete(a);
|
|
35
|
+
return e || t;
|
|
36
|
+
}
|
|
37
|
+
let s = x.get(a) ?? /* @__PURE__ */ new Set(), c = S.get(a) ?? 0, d = e(o, h, g);
|
|
38
|
+
return x.set(a, d.icons), d.dynamicNames > 0 ? S.set(a, d.dynamicNames) : S.delete(a), !p(s, d.icons) || c !== d.dynamicNames;
|
|
39
|
+
}, k = async (e) => {
|
|
40
|
+
x.clear(), S.clear();
|
|
41
|
+
for (let t of _) {
|
|
42
|
+
let r = f(w, t), i;
|
|
43
|
+
try {
|
|
44
|
+
i = await n(r);
|
|
45
|
+
} catch {
|
|
46
|
+
e?.warn(`[@dubium/icons] Директория для сканирования недоступна: "${t}".\nПроверьте options.scan, существование пути и права доступа.`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
for (let t of i) e?.addWatchFile(t), await O(t);
|
|
50
|
+
}
|
|
51
|
+
}, A = async () => {
|
|
52
|
+
C = await Promise.all(y.map((e) => a(w, e)));
|
|
53
|
+
}, j = (e) => y.some((t) => r(f(w, t.path), e)), M = (e) => _.some((t) => r(f(w, t), e)), N = () => {
|
|
54
|
+
if (!T) return;
|
|
55
|
+
let e = T.moduleGraph.getModuleById(s);
|
|
56
|
+
e && T.moduleGraph.invalidateModule(e), T.ws.send({ type: "full-reload" });
|
|
57
|
+
}, P = (e) => {
|
|
58
|
+
if (S.size === 0) {
|
|
59
|
+
E = "";
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let t = [...S.entries()].sort(([e], [t]) => e.localeCompare(t)).map(([e, t]) => ` - ${i(d(w, e))}: ${t}`).join("\n");
|
|
63
|
+
t !== E && (E = t, e(`[@dubium/icons] Найдены динамические <Icon name={...}>:\n${t}\nДля MF/EventBus это допустимо, если loader регистрируется remote через runtime registry.`));
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
name: "dubium-icons",
|
|
67
|
+
enforce: "pre",
|
|
68
|
+
configResolved(e) {
|
|
69
|
+
w = e.root;
|
|
70
|
+
},
|
|
71
|
+
async buildStart() {
|
|
72
|
+
await A(), await k(this), P((e) => this.warn(e));
|
|
73
|
+
},
|
|
74
|
+
configureServer(e) {
|
|
75
|
+
T = e;
|
|
76
|
+
for (let t of y) e.watcher.add(f(w, t.path));
|
|
77
|
+
let t = async (e) => {
|
|
78
|
+
let t = j(e), n = M(e) ? await O(e) : !1, r = () => {
|
|
79
|
+
N(), P((e) => {
|
|
80
|
+
T?.config.logger.warn(e);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
if (t) {
|
|
84
|
+
await A(), r();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
n && r();
|
|
88
|
+
};
|
|
89
|
+
e.watcher.on("add", t), e.watcher.on("unlink", t), e.watcher.on("addDir", t), e.watcher.on("unlinkDir", t), e.httpServer?.once("close", () => {
|
|
90
|
+
e.watcher.off("add", t), e.watcher.off("unlink", t), e.watcher.off("addDir", t), e.watcher.off("unlinkDir", t);
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
resolveId(e) {
|
|
94
|
+
return e === "virtual:@dubium/icons-registry" ? s : null;
|
|
95
|
+
},
|
|
96
|
+
load(e) {
|
|
97
|
+
return e === s ? c(D(), C, b, (e) => this.resolve(e)) : null;
|
|
98
|
+
},
|
|
99
|
+
async handleHotUpdate(e) {
|
|
100
|
+
if (M(e.file) && await O(e.file, e.read)) return N(), P((e) => this.warn(e)), [];
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
export { m as dubiumIcons };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Источник, из которого разрешаются имена иконок.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Поддерживается два варианта: локальный каталог компонентов (`local`)
|
|
6
|
+
* и fallback-шаблон импорта из npm-пакета (`package`).
|
|
7
|
+
*/
|
|
8
|
+
export type TDubiumIconSource = {
|
|
9
|
+
/**
|
|
10
|
+
* Локальный источник иконок.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* `UserIcon.tsx` при suffix `Icon` даёт имя `User`.
|
|
14
|
+
*/
|
|
15
|
+
type: "local";
|
|
16
|
+
/**
|
|
17
|
+
* Путь к директории с компонентами относительно Vite root.
|
|
18
|
+
*/
|
|
19
|
+
path: string;
|
|
20
|
+
/**
|
|
21
|
+
* Суффикс имени файла, по которому распознаются компоненты иконок.
|
|
22
|
+
*
|
|
23
|
+
* @default "Icon"
|
|
24
|
+
*/
|
|
25
|
+
suffix?: string;
|
|
26
|
+
} | {
|
|
27
|
+
/**
|
|
28
|
+
* Package fallback для иконок, отсутствующих в local sources.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Допускается не более одного `package` source.
|
|
32
|
+
* Шаблон должен содержать `{name}`.
|
|
33
|
+
*/
|
|
34
|
+
type: "package";
|
|
35
|
+
/**
|
|
36
|
+
* Шаблон пути импорта.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* `@dubium/icons/icons/{name}`
|
|
40
|
+
*/
|
|
41
|
+
importPattern: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Настройки Vite-плагина {@link dubiumIcons}.
|
|
45
|
+
*/
|
|
46
|
+
export interface DubiumIconsPluginOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Дополнительные имена JSX-компонентов, которые scanner должен считать
|
|
49
|
+
* компонентами иконок независимо от import source.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* Обычный `Icon` из `@dubium/icons/vite` определяется автоматически,
|
|
53
|
+
* включая alias. Эту настройку следует использовать только для собственных
|
|
54
|
+
* обёрток или нестандартных компонентов.
|
|
55
|
+
*
|
|
56
|
+
* @default []
|
|
57
|
+
*/
|
|
58
|
+
componentNames?: readonly string[];
|
|
59
|
+
/**
|
|
60
|
+
* Дополнительные строковые поля, которые считаются ссылками на иконки.
|
|
61
|
+
*
|
|
62
|
+
* @remarks
|
|
63
|
+
* Пустой массив отключает сканирование дополнительных свойств.
|
|
64
|
+
*
|
|
65
|
+
* @default []
|
|
66
|
+
*/
|
|
67
|
+
propertyNames?: readonly string[];
|
|
68
|
+
/**
|
|
69
|
+
* Директории проекта, которые нужно сканировать.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
* Пустой массив полностью отключает сканирование директорий.
|
|
73
|
+
*
|
|
74
|
+
* @default ["src"]
|
|
75
|
+
*/
|
|
76
|
+
scan?: readonly string[];
|
|
77
|
+
/**
|
|
78
|
+
* Источники иконок.
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* Можно указать несколько `local` sources; они проверяются сверху вниз.
|
|
82
|
+
* Дополнительно можно указать максимум один `package` source,
|
|
83
|
+
* который используется как fallback.
|
|
84
|
+
*
|
|
85
|
+
* Пустой массив означает, что автоматические источники
|
|
86
|
+
* иконок использоваться не будут.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* dubiumIcons({
|
|
91
|
+
* sources: [
|
|
92
|
+
* { type: "local", path: "src/icons" },
|
|
93
|
+
* { type: "package", importPattern: "@dubium/icons/icons/{name}" },
|
|
94
|
+
* ],
|
|
95
|
+
* })
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
sources?: readonly TDubiumIconSource[];
|
|
99
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Публичный API модуля сканера исходников.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Экспортирует {@link scanSource} — функцию, которая собирает статические
|
|
6
|
+
* имена иконок из JSX-тегов, импортов `Icon` и строковых свойств.
|
|
7
|
+
*/
|
|
8
|
+
export { scanSource } from "./scanner.source.js";
|
|
9
|
+
export type { ScanResult } from "./scanner.types.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { REGEX as e } from "./scanner.regex.js";
|
|
2
|
+
import { isIdentifierCharacter as t, walkCode as n } from "./scanner.lexical.js";
|
|
3
|
+
//#region src/icons/vite/plugin/scanner/scanner.imports.ts
|
|
4
|
+
var r = "@dubium/icons/vite", i = (e, n, r) => {
|
|
5
|
+
if (!e.startsWith(r, n)) return !1;
|
|
6
|
+
let i = e[n - 1], a = e[n + r.length];
|
|
7
|
+
return !t(i) && !t(a);
|
|
8
|
+
}, a = (t) => t.replace(e.COMMENTS.MULTILINE, " ").replace(e.COMMENTS.SINGLE_LINE, " "), o = (t, n) => {
|
|
9
|
+
let i = t.slice(n), o = e.IMPORT.STATEMENT.exec(i);
|
|
10
|
+
if (!o) return null;
|
|
11
|
+
let [s, c, , l] = o;
|
|
12
|
+
if (l !== r) return null;
|
|
13
|
+
let u = [], d = a(c).split(",");
|
|
14
|
+
for (let t of d) {
|
|
15
|
+
let n = t.trim();
|
|
16
|
+
if (!n || n.startsWith("type ")) continue;
|
|
17
|
+
let r = e.IMPORT.ICON_SPECIFIER.exec(n);
|
|
18
|
+
r && u.push(r[1] ?? "Icon");
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
componentNames: u,
|
|
22
|
+
endIndex: n + o[0].length
|
|
23
|
+
};
|
|
24
|
+
}, s = (e) => {
|
|
25
|
+
let t = /* @__PURE__ */ new Set();
|
|
26
|
+
return n(e, ({ index: n, skipTo: r }) => {
|
|
27
|
+
if (!i(e, n, "import")) return;
|
|
28
|
+
let a = o(e, n);
|
|
29
|
+
if (a) {
|
|
30
|
+
for (let e of a.componentNames) t.add(e);
|
|
31
|
+
r(a.endIndex);
|
|
32
|
+
}
|
|
33
|
+
}), [...t];
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
export { s as findImportedIconComponentNames };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Находит позиции всех JSX-тегов компонентов иконок в исходном тексте.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Общий lexical walker игнорирует комментарии, строки, template literals
|
|
6
|
+
* и RegExp literals, поэтому ложные `<Icon>` внутри них не учитываются.
|
|
7
|
+
*/
|
|
8
|
+
export declare const findComponentTagStarts: (source: string, componentNames: readonly string[]) => number[];
|
|
9
|
+
/**
|
|
10
|
+
* Находит индекс закрывающей угловой скобки открывающего JSX-тега.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Поиск учитывает содержимое строк и шаблонных строк, а также глубину вложенности
|
|
14
|
+
* фигурных скобок `{}` JSX-выражений.
|
|
15
|
+
*/
|
|
16
|
+
export declare const findTagEnd: (source: string, startIndex: number) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Извлекает статическое значение атрибута `name` из открывающего JSX-тега.
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseStaticName: (openingTag: string) => string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Проверяет, присутствует ли у открывающего JSX-тега атрибут `name`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const hasNameAttribute: (openingTag: string) => boolean;
|