Skip to content

Commit 70e2fe1

Browse files
committed
feat: Add SVG sprite pipeline and switch to sprite-based icons
- When moving from element-ui to element plus, we lost the built-in icon font. Element plus has icon library which is Vue specific. To avoid dependency, we are switching to an SVG sprite approach for icons as we only need a few icons. - Integrate an in-house SvgSpritePlugin into build/webpack.config.js - Special handling for svg icons loading (include iconDir, support ?inline) - Add UI icon SVGs in use - update components to use sprite <svg><use href="/asset/sprite.svg#...">
1 parent fab40a4 commit 70e2fe1

File tree

11 files changed

+188
-23
lines changed

11 files changed

+188
-23
lines changed

build/webpack.config.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ const { VueLoaderPlugin } = require('vue-loader');
33
const path = require('path');
44
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
55
const fs = require('fs');
6+
const SvgSpritePlugin = require('../tool/plugin-svg-sprite');
67

78
const distPath = path.resolve(__dirname, '../public');
9+
const iconDir = path.resolve(__dirname, '../src/asset/icon');
810

911
module.exports = (env, argv) => {
1012
const isDev = argv.mode === 'development';
@@ -78,8 +80,28 @@ module.exports = (env, argv) => {
7880
}
7981
]
8082
},
83+
// SVG for Sprite Generation
8184
{
82-
test: /\.(svg|html)$/,
85+
test: /\.svg$/,
86+
include: iconDir,
87+
resourceQuery: { not: [/inline/] }, // DOES NOT match '?inline'
88+
type: 'asset/source'
89+
},
90+
// SVG for Raw Inline Use (Using ?inline suffix)
91+
{
92+
test: /\.svg$/,
93+
include: iconDir,
94+
resourceQuery: /inline/, // Matches imports like '...share.svg?inline'
95+
type: 'asset/source'
96+
},
97+
// Catch-all for other SVGs (logos, etc.) outside the icon directory
98+
{
99+
test: /\.svg$/,
100+
exclude: iconDir,
101+
type: 'asset/resource'
102+
},
103+
{
104+
test: /\.html$/,
83105
use: [
84106
{
85107
loader: 'html-loader',
@@ -116,6 +138,10 @@ module.exports = (env, argv) => {
116138
vue: 'Vue'
117139
},
118140
plugins: [
141+
new SvgSpritePlugin({
142+
spriteFilename: '../asset/sprite.svg',
143+
iconDir: iconDir
144+
}),
119145
new webpack.DefinePlugin({
120146
// It can be used in the code directly.
121147
CONFIG_LOCAL: JSON.stringify(configLocal)

src/asset/icon/ui/camera.svg

Lines changed: 3 additions & 0 deletions
Loading

src/asset/icon/ui/document.svg

Lines changed: 3 additions & 0 deletions
Loading

src/asset/icon/ui/download.svg

Lines changed: 3 additions & 0 deletions
Loading

src/asset/icon/ui/loading.svg

Lines changed: 3 additions & 0 deletions
Loading

src/asset/icon/ui/setting.svg

Lines changed: 3 additions & 0 deletions
Loading

src/asset/icon/ui/share.svg

Lines changed: 3 additions & 0 deletions
Loading

src/editor/Editor.vue

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,14 @@
317317
<template #label>
318318
<span>
319319
{{ t('editor.prPreview.review') }}
320-
<i
320+
<svg
321+
role="img"
321322
v-if="isPRReviewLoading"
322-
class="el-icon-loading"
323+
class="icon"
323324
style="margin-left: 5px"
324-
></i>
325+
>
326+
<use href="/asset/sprite.svg#loading"></use>
327+
</svg>
325328
</span>
326329
</template>
327330
<span v-if="isPRReviewLoading">{{
@@ -384,11 +387,14 @@
384387
<details @toggle="$event.target.open && loadPRDiff()">
385388
<summary style="display: revert; cursor: pointer">
386389
{{ t('editor.prPreview.viewDiff') }}
387-
<i
390+
<svg
391+
role="img"
388392
v-if="isPRDiffLoading"
389-
class="el-icon-loading"
393+
class="icon"
390394
style="margin-left: 5px"
391-
></i>
395+
>
396+
<use href="/asset/sprite.svg#loading"></use>
397+
</svg>
392398
</summary>
393399
<pre
394400
class="pr-diff"
@@ -650,7 +656,7 @@ function updateOptionOutline() {
650656
: `https://echarts.apache.org/${lang}/option.html#${hash.join('.')}`;
651657
return !isObjOrArray
652658
? `<a href="${link}" target="_blank" title="${tipTitle}">${name}</a>`
653-
: `${name}<a href="${link}" target="_blank" title="${tipTitle}"><i class="el-icon-document"></i></a>`;
659+
: `${name}<a href="${link}" target="_blank" title="${tipTitle}"><i><svg role="img" class="icon icon-document"><use href="/asset/sprite.svg#document"></use></svg></i></a>`;
654660
},
655661
expandOnCreatedAndUpdated(path) {
656662
return path.length === 0 || (path[0] === 'series' && path.length <= 1);
@@ -980,7 +986,7 @@ $handler-width: 15px;
980986
font-family: 'Source Code Pro', 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas',
981987
monospace;
982988
983-
.el-icon-document {
989+
.icon-document {
984990
margin-left: 5px;
985991
font-size: 1rem;
986992

src/editor/Preview.vue

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@
4646
<template #reference>
4747
<span class="render-config-trigger">
4848
<el-button size="small">
49-
{{ t('editor.renderCfgTitle')
50-
}}<i class="el-icon-setting el-icon--right"></i>
49+
{{ t('editor.renderCfgTitle') }}
50+
<svg role="img" class="icon ml-4">
51+
<use href="/asset/sprite.svg#setting"></use>
52+
</svg>
5153
</el-button>
5254
</span>
5355
</template>
@@ -108,27 +110,30 @@
108110
<div class="left-buttons">
109111
<template v-if="inEditor && !shared.isMobile">
110112
<el-button
111-
icon="el-icon-download"
112113
size="small"
113114
@click="downloadExample"
114115
:title="t('editor.download') + ' (HTML)'"
115116
>
116-
{{ t('editor.download') }}
117+
<svg role="img" class="icon mr-4">
118+
<use href="/asset/sprite.svg#download"></use>
119+
</svg>
120+
<span>{{ t('editor.download') }}</span>
117121
</el-button>
118-
<el-button
119-
@click="screenshot"
120-
icon="el-icon-camera-solid"
121-
size="small"
122-
>
123-
{{ t('editor.screenshot') }}
122+
<el-button @click="screenshot" size="small">
123+
<svg role="img" class="icon mr-4">
124+
<use href="/asset/sprite.svg#camera"></use>
125+
</svg>
126+
<span>{{ t('editor.screenshot') }}</span>
124127
</el-button>
125128
<el-button
126129
@click="share"
127-
icon="el-icon-share"
128130
size="small"
129131
:title="t('editor.share.tooltip')"
130132
>
131-
{{ t('editor.share.title') }}
133+
<svg role="img" class="icon mr-4">
134+
<use href="/asset/sprite.svg#share"></use>
135+
</svg>
136+
<span>{{ t('editor.share.title') }}</span>
132137
</el-button>
133138
</template>
134139
</div>
@@ -887,4 +892,17 @@ defineExpose({
887892
}
888893
}
889894
}
895+
896+
.icon {
897+
width: 12px;
898+
height: 12px;
899+
}
900+
901+
.ml-4 {
902+
margin-left: 4px;
903+
}
904+
905+
.mr-4 {
906+
margin-right: 4px;
907+
}
890908
</style>

src/explore/Explore.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ const icons = {};
105105
'rich',
106106
'graphic'
107107
].forEach(function (category) {
108-
icons[category] = require('../asset/icon/' + category + '.svg');
108+
icons[category] = require('../asset/icon/' + category + '.svg?inline');
109109
});
110110
111-
const glIcon = require('../asset/icon/gl.svg');
111+
const glIcon = require('../asset/icon/gl.svg?inline');
112112
[
113113
'globe',
114114
'bar3D',

0 commit comments

Comments
 (0)