Commit 15b429545d2c569d3239fa92bfeaba36793cd8a8
Committed by
xp.Huang
1 parent
ca2665aa
perf: 使用离线Icon图标
Showing
6 changed files
with
248 additions
and
1 deletions
build/generate/iconfont/offline.icon.ts
0 → 100644
1 | +import { IconifyJSON } from '@iconify/iconify'; | ||
2 | +import { camelCase } from 'lodash-es'; | ||
3 | + | ||
4 | +interface IconType { | ||
5 | + prefix: string; | ||
6 | + icon: string; | ||
7 | + alias?: string; | ||
8 | +} | ||
9 | + | ||
10 | +export function getCacheIcons() { | ||
11 | + const storageKeys = Object.keys(localStorage); | ||
12 | + | ||
13 | + const iconifyKeys = storageKeys.filter((key) => key.startsWith('iconify')); | ||
14 | + | ||
15 | + const allIcons: IconType[] = []; | ||
16 | + for (const key of iconifyKeys) { | ||
17 | + try { | ||
18 | + const res: Record<'data', IconifyJSON> = JSON.parse(localStorage.getItem(key)!); | ||
19 | + | ||
20 | + const { | ||
21 | + data: { prefix, icons, aliases }, | ||
22 | + } = res; | ||
23 | + | ||
24 | + allIcons.push(...Object.keys(icons).map((icon) => ({ icon, prefix }))); | ||
25 | + | ||
26 | + allIcons.push( | ||
27 | + ...Object.entries(aliases || {}).map(([key, value]) => ({ | ||
28 | + icon: key, | ||
29 | + alias: value.parent, | ||
30 | + prefix, | ||
31 | + })) | ||
32 | + ); | ||
33 | + } catch { | ||
34 | + continue; | ||
35 | + } | ||
36 | + } | ||
37 | + | ||
38 | + const collect = allIcons.reduce((prev, next) => { | ||
39 | + if (Reflect.has(prev, next.prefix)) { | ||
40 | + prev[next.prefix].push(next); | ||
41 | + } else { | ||
42 | + prev[next.prefix] = [next]; | ||
43 | + } | ||
44 | + return prev; | ||
45 | + }, {} as Record<string, IconType[]>); | ||
46 | + | ||
47 | + const icons = Object.entries(collect).reduce( | ||
48 | + (prev, [key, value]) => { | ||
49 | + for (const { icon, alias } of value) { | ||
50 | + const importName = camelCase(`${key}-${alias || icon}`); | ||
51 | + | ||
52 | + prev.imports.push( | ||
53 | + `import ${importName} from 'virtual:@iconify/json/${key}/${alias || icon}';` | ||
54 | + ); | ||
55 | + | ||
56 | + prev.registerIcons.push(`addIcon('${key}:${icon}', ${importName});`); | ||
57 | + } | ||
58 | + | ||
59 | + return prev; | ||
60 | + }, | ||
61 | + { imports: [], registerIcons: [] } as Record<'imports' | 'registerIcons', string[]> | ||
62 | + ); | ||
63 | + | ||
64 | + return `${[...new Set(icons.imports)].join('\n')}\n${[...new Set(icons.registerIcons)].join( | ||
65 | + '\n' | ||
66 | + )}`; | ||
67 | +} |
build/vite/plugin/iconify.ts
0 → 100644
1 | +import { existsSync, readFileSync } from 'fs'; | ||
2 | +import { Plugin } from 'vite'; | ||
3 | +import { IconifyJSON } from '@iconify/iconify'; | ||
4 | + | ||
5 | +const Plugin_Name = '@iconify-icon-offline-import'; | ||
6 | + | ||
7 | +const baseMsg = (msg: string) => `[${Plugin_Name}] ${msg}`; | ||
8 | + | ||
9 | +export default function IconifyPlugin(): Plugin { | ||
10 | + const virtualModuleId = 'virtual:@iconify/json'; | ||
11 | + | ||
12 | + const cache: Record<string, IconifyJSON> = {}; | ||
13 | + | ||
14 | + return { | ||
15 | + name: 'iconify-json-tree-sharking', | ||
16 | + resolveId(id) { | ||
17 | + if (id.includes(virtualModuleId)) { | ||
18 | + return '\0' + id; | ||
19 | + } | ||
20 | + }, | ||
21 | + async load(id) { | ||
22 | + if (id.includes(virtualModuleId)) { | ||
23 | + const iconPaths = id.split(virtualModuleId); | ||
24 | + const iconPath = iconPaths[iconPaths.length - 1]; | ||
25 | + | ||
26 | + if (!iconPath) return 'export default {}'; | ||
27 | + | ||
28 | + const [collectName, iconName] = iconPath.split('/').filter(Boolean); | ||
29 | + | ||
30 | + const collectPath = require.resolve(`@iconify/json/json/${collectName}.json`); | ||
31 | + | ||
32 | + if (!existsSync(collectPath)) { | ||
33 | + const msg = baseMsg(`Can't found virtual:@iconify/json/${collectName}/${iconName}.`); | ||
34 | + throw new Error(msg); | ||
35 | + } | ||
36 | + | ||
37 | + let collect: IconifyJSON; | ||
38 | + if (cache[collectName]) { | ||
39 | + collect = cache[collectName]; | ||
40 | + } else { | ||
41 | + const res = readFileSync(collectPath, { | ||
42 | + encoding: 'utf-8', | ||
43 | + }); | ||
44 | + collect = JSON.parse(res); | ||
45 | + cache[collectName] = collect; | ||
46 | + } | ||
47 | + | ||
48 | + if (Object.hasOwn(collect.icons, iconName)) { | ||
49 | + return `export default ${JSON.stringify( | ||
50 | + Object.assign(collect.icons[iconName], { | ||
51 | + width: collect.width, | ||
52 | + height: collect.height, | ||
53 | + }), | ||
54 | + null, | ||
55 | + 2 | ||
56 | + )}`; | ||
57 | + } else { | ||
58 | + const msg = baseMsg(`Can't found ${iconName} from ${collectName} collect.`); | ||
59 | + throw new Error(msg); | ||
60 | + } | ||
61 | + } | ||
62 | + }, | ||
63 | + }; | ||
64 | +} |
@@ -16,6 +16,7 @@ import { configThemePlugin } from './theme'; | @@ -16,6 +16,7 @@ import { configThemePlugin } from './theme'; | ||
16 | import { configImageminPlugin } from './imagemin'; | 16 | import { configImageminPlugin } from './imagemin'; |
17 | import { configSvgIconsPlugin } from './svgSprite'; | 17 | import { configSvgIconsPlugin } from './svgSprite'; |
18 | import { configHmrPlugin } from './hmr'; | 18 | import { configHmrPlugin } from './hmr'; |
19 | +import IconifyPlugin from './iconify'; | ||
19 | 20 | ||
20 | export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { | 21 | export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { |
21 | const { | 22 | const { |
@@ -77,5 +78,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { | @@ -77,5 +78,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { | ||
77 | vitePlugins.push(configPwaConfig(viteEnv)); | 78 | vitePlugins.push(configPwaConfig(viteEnv)); |
78 | } | 79 | } |
79 | 80 | ||
81 | + vitePlugins.push(IconifyPlugin()); | ||
80 | return vitePlugins; | 82 | return vitePlugins; |
81 | } | 83 | } |
@@ -87,7 +87,7 @@ | @@ -87,7 +87,7 @@ | ||
87 | "devDependencies": { | 87 | "devDependencies": { |
88 | "@commitlint/cli": "^13.1.0", | 88 | "@commitlint/cli": "^13.1.0", |
89 | "@commitlint/config-conventional": "^13.1.0", | 89 | "@commitlint/config-conventional": "^13.1.0", |
90 | - "@iconify/json": "^1.1.386", | 90 | + "@iconify/json": "^2.2.257", |
91 | "@purge-icons/generated": "^0.7.0", | 91 | "@purge-icons/generated": "^0.7.0", |
92 | "@types/codemirror": "^5.60.2", | 92 | "@types/codemirror": "^5.60.2", |
93 | "@types/crypto-js": "^4.0.2", | 93 | "@types/crypto-js": "^4.0.2", |
src/components/Icon/data/offline.icon.ts
0 → 100644
1 | +import antDesignGoldOutlined from 'virtual:@iconify/json/ant-design/gold-outlined'; | ||
2 | +import antDesignHomeOutlined from 'virtual:@iconify/json/ant-design/home-outlined'; | ||
3 | +import antDesignIssuesCloseOutlined from 'virtual:@iconify/json/ant-design/issues-close-outlined'; | ||
4 | +import antDesignMacCommandOutlined from 'virtual:@iconify/json/ant-design/mac-command-outlined'; | ||
5 | +import antDesignMessageOutlined from 'virtual:@iconify/json/ant-design/message-outlined'; | ||
6 | +import antDesignMobileOutlined from 'virtual:@iconify/json/ant-design/mobile-outlined'; | ||
7 | +import antDesignNotificationOutlined from 'virtual:@iconify/json/ant-design/notification-outlined'; | ||
8 | +import antDesignPieChartOutlined from 'virtual:@iconify/json/ant-design/pie-chart-outlined'; | ||
9 | +import antDesignProjectOutlined from 'virtual:@iconify/json/ant-design/project-outlined'; | ||
10 | +import antDesignProjectTwotone from 'virtual:@iconify/json/ant-design/project-twotone'; | ||
11 | +import antDesignReconciliationOutlined from 'virtual:@iconify/json/ant-design/reconciliation-outlined'; | ||
12 | +import antDesignSelectOutlined from 'virtual:@iconify/json/ant-design/select-outlined'; | ||
13 | +import antDesignShoppingOutlined from 'virtual:@iconify/json/ant-design/shopping-outlined'; | ||
14 | +import antDesignSoundOutlined from 'virtual:@iconify/json/ant-design/sound-outlined'; | ||
15 | +import antDesignSwapOutlined from 'virtual:@iconify/json/ant-design/swap-outlined'; | ||
16 | +import antDesignTagsOutlined from 'virtual:@iconify/json/ant-design/tags-outlined'; | ||
17 | +import antDesignUngroupOutlined from 'virtual:@iconify/json/ant-design/ungroup-outlined'; | ||
18 | +import antDesignVideoCameraAddOutlined from 'virtual:@iconify/json/ant-design/video-camera-add-outlined'; | ||
19 | +import antDesignVideoCameraOutlined from 'virtual:@iconify/json/ant-design/video-camera-outlined'; | ||
20 | +import antDesignAlertOutlined from 'virtual:@iconify/json/ant-design/alert-outlined'; | ||
21 | +import antDesignAliyunOutlined from 'virtual:@iconify/json/ant-design/aliyun-outlined'; | ||
22 | +import antDesignBarChartOutlined from 'virtual:@iconify/json/ant-design/bar-chart-outlined'; | ||
23 | +import antDesignBookTwotone from 'virtual:@iconify/json/ant-design/book-twotone'; | ||
24 | +import antDesignBorderBottomOutlined from 'virtual:@iconify/json/ant-design/border-bottom-outlined'; | ||
25 | +import antDesignBorderOuterOutlined from 'virtual:@iconify/json/ant-design/border-outer-outlined'; | ||
26 | +import antDesignBranchesOutlined from 'virtual:@iconify/json/ant-design/branches-outlined'; | ||
27 | +import antDesignCalculatorTwotone from 'virtual:@iconify/json/ant-design/calculator-twotone'; | ||
28 | +import antDesignCalendarFilled from 'virtual:@iconify/json/ant-design/calendar-filled'; | ||
29 | +import antDesignCloudServerOutlined from 'virtual:@iconify/json/ant-design/cloud-server-outlined'; | ||
30 | +import antDesignCodeOutlined from 'virtual:@iconify/json/ant-design/code-outlined'; | ||
31 | +import antDesignContactsOutlined from 'virtual:@iconify/json/ant-design/contacts-outlined'; | ||
32 | +import antDesignContainerOutlined from 'virtual:@iconify/json/ant-design/container-outlined'; | ||
33 | +import antDesignContainerTwotone from 'virtual:@iconify/json/ant-design/container-twotone'; | ||
34 | +import antDesignCopyTwotone from 'virtual:@iconify/json/ant-design/copy-twotone'; | ||
35 | +import antDesignDashboardOutlined from 'virtual:@iconify/json/ant-design/dashboard-outlined'; | ||
36 | +import antDesignDeploymentUnitOutlined from 'virtual:@iconify/json/ant-design/deployment-unit-outlined'; | ||
37 | +import antDesignEnvironmentOutlined from 'virtual:@iconify/json/ant-design/environment-outlined'; | ||
38 | +import antDesignExceptionOutlined from 'virtual:@iconify/json/ant-design/exception-outlined'; | ||
39 | +import antDesignFileAddOutlined from 'virtual:@iconify/json/ant-design/file-add-outlined'; | ||
40 | +import antDesignFileDoneOutlined from 'virtual:@iconify/json/ant-design/file-done-outlined'; | ||
41 | +import antDesignFileMarkdownOutlined from 'virtual:@iconify/json/ant-design/file-markdown-outlined'; | ||
42 | +import antDesignFilePptOutlined from 'virtual:@iconify/json/ant-design/file-ppt-outlined'; | ||
43 | +import antDesignFileTextOutlined from 'virtual:@iconify/json/ant-design/file-text-outlined'; | ||
44 | +import materialSymbolsCallMade from 'virtual:@iconify/json/material-symbols/call-made'; | ||
45 | +import materialSymbolsUpload from 'virtual:@iconify/json/material-symbols/upload'; | ||
46 | +import materialSymbolsInputSharp from 'virtual:@iconify/json/material-symbols/input-sharp'; | ||
47 | +import materialSymbolsMenu from 'virtual:@iconify/json/material-symbols/menu'; | ||
48 | +import materialSymbolsSms from 'virtual:@iconify/json/material-symbols/sms'; | ||
49 | +import materialSymbolsBackup from 'virtual:@iconify/json/material-symbols/backup'; | ||
50 | +import materialSymbolsFilterList from 'virtual:@iconify/json/material-symbols/filter-list'; | ||
51 | +import materialSymbolsFlashOn from 'virtual:@iconify/json/material-symbols/flash-on'; | ||
52 | +import materialSymbolsSearch from 'virtual:@iconify/json/material-symbols/search'; | ||
53 | +import materialSymbolsSettingsEthernet from 'virtual:@iconify/json/material-symbols/settings-ethernet'; | ||
54 | +import mdiCheck from 'virtual:@iconify/json/mdi/check'; | ||
55 | +import { addIcon } from '@iconify/iconify'; | ||
56 | + | ||
57 | +addIcon('ant-design:gold-outlined', antDesignGoldOutlined); | ||
58 | +addIcon('ant-design:home-outlined', antDesignHomeOutlined); | ||
59 | +addIcon('ant-design:issues-close-outlined', antDesignIssuesCloseOutlined); | ||
60 | +addIcon('ant-design:mac-command-outlined', antDesignMacCommandOutlined); | ||
61 | +addIcon('ant-design:message-outlined', antDesignMessageOutlined); | ||
62 | +addIcon('ant-design:mobile-outlined', antDesignMobileOutlined); | ||
63 | +addIcon('ant-design:notification-outlined', antDesignNotificationOutlined); | ||
64 | +addIcon('ant-design:pie-chart-outlined', antDesignPieChartOutlined); | ||
65 | +addIcon('ant-design:project-outlined', antDesignProjectOutlined); | ||
66 | +addIcon('ant-design:project-twotone', antDesignProjectTwotone); | ||
67 | +addIcon('ant-design:reconciliation-outlined', antDesignReconciliationOutlined); | ||
68 | +addIcon('ant-design:select-outlined', antDesignSelectOutlined); | ||
69 | +addIcon('ant-design:shopping-outlined', antDesignShoppingOutlined); | ||
70 | +addIcon('ant-design:sound-outlined', antDesignSoundOutlined); | ||
71 | +addIcon('ant-design:swap-outlined', antDesignSwapOutlined); | ||
72 | +addIcon('ant-design:tags-outlined', antDesignTagsOutlined); | ||
73 | +addIcon('ant-design:ungroup-outlined', antDesignUngroupOutlined); | ||
74 | +addIcon('ant-design:video-camera-add-outlined', antDesignVideoCameraAddOutlined); | ||
75 | +addIcon('ant-design:video-camera-outlined', antDesignVideoCameraOutlined); | ||
76 | +addIcon('ant-design:alert-outlined', antDesignAlertOutlined); | ||
77 | +addIcon('ant-design:aliyun-outlined', antDesignAliyunOutlined); | ||
78 | +addIcon('ant-design:bar-chart-outlined', antDesignBarChartOutlined); | ||
79 | +addIcon('ant-design:book-twotone', antDesignBookTwotone); | ||
80 | +addIcon('ant-design:border-bottom-outlined', antDesignBorderBottomOutlined); | ||
81 | +addIcon('ant-design:border-outer-outlined', antDesignBorderOuterOutlined); | ||
82 | +addIcon('ant-design:branches-outlined', antDesignBranchesOutlined); | ||
83 | +addIcon('ant-design:calculator-twotone', antDesignCalculatorTwotone); | ||
84 | +addIcon('ant-design:calendar-filled', antDesignCalendarFilled); | ||
85 | +addIcon('ant-design:cloud-server-outlined', antDesignCloudServerOutlined); | ||
86 | +addIcon('ant-design:code-outlined', antDesignCodeOutlined); | ||
87 | +addIcon('ant-design:contacts-outlined', antDesignContactsOutlined); | ||
88 | +addIcon('ant-design:container-outlined', antDesignContainerOutlined); | ||
89 | +addIcon('ant-design:container-twotone', antDesignContainerTwotone); | ||
90 | +addIcon('ant-design:copy-twotone', antDesignCopyTwotone); | ||
91 | +addIcon('ant-design:dashboard-outlined', antDesignDashboardOutlined); | ||
92 | +addIcon('ant-design:deployment-unit-outlined', antDesignDeploymentUnitOutlined); | ||
93 | +addIcon('ant-design:environment-outlined', antDesignEnvironmentOutlined); | ||
94 | +addIcon('ant-design:exception-outlined', antDesignExceptionOutlined); | ||
95 | +addIcon('ant-design:file-add-outlined', antDesignFileAddOutlined); | ||
96 | +addIcon('ant-design:file-done-outlined', antDesignFileDoneOutlined); | ||
97 | +addIcon('ant-design:file-markdown-outlined', antDesignFileMarkdownOutlined); | ||
98 | +addIcon('ant-design:file-ppt-outlined', antDesignFilePptOutlined); | ||
99 | +addIcon('ant-design:file-text-outlined', antDesignFileTextOutlined); | ||
100 | +addIcon('material-symbols:call-made', materialSymbolsCallMade); | ||
101 | +addIcon('material-symbols:upload', materialSymbolsUpload); | ||
102 | +addIcon('material-symbols:input-sharp', materialSymbolsInputSharp); | ||
103 | +addIcon('material-symbols:menu', materialSymbolsMenu); | ||
104 | +addIcon('material-symbols:sms', materialSymbolsSms); | ||
105 | +addIcon('material-symbols:file-upload', materialSymbolsUpload); | ||
106 | +addIcon('material-symbols:backup', materialSymbolsBackup); | ||
107 | +addIcon('material-symbols:filter-list', materialSymbolsFilterList); | ||
108 | +addIcon('material-symbols:flash-on', materialSymbolsFlashOn); | ||
109 | +addIcon('material-symbols:search', materialSymbolsSearch); | ||
110 | +addIcon('material-symbols:settings-ethernet', materialSymbolsSettingsEthernet); | ||
111 | +addIcon('material-symbols:cloud-upload', materialSymbolsBackup); | ||
112 | +addIcon('mdi:check', mdiCheck); | ||
113 | +addIcon('mdi:tick', mdiCheck); |
1 | import Icon from './src/Icon.vue'; | 1 | import Icon from './src/Icon.vue'; |
2 | import SvgIcon from './src/SvgIcon.vue'; | 2 | import SvgIcon from './src/SvgIcon.vue'; |
3 | import IconPicker from './src/IconPicker.vue'; | 3 | import IconPicker from './src/IconPicker.vue'; |
4 | +import './data/offline.icon'; | ||
4 | 5 | ||
5 | export { Icon, IconPicker, SvgIcon }; | 6 | export { Icon, IconPicker, SvgIcon }; |
6 | 7 |