mirror of
https://github.com/antfu-collective/icones.git
synced 2026-01-09 07:40:49 +08:00
feat: use ESM svg-packer with Vite (#364)
Co-authored-by: Anthony Fu <github@antfu.me>
This commit is contained in:
parent
5dbe68f16b
commit
5e8ea588db
@ -7,8 +7,6 @@
|
||||
<link rel="icon" href="/favicon.svg" />
|
||||
<link rel="icon" href="/favicon-dark.svg" media="(prefers-color-scheme: light)" />
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="/search.xml" title="Icônes" />
|
||||
<script src="/lib/svg-packer.js" defer></script>
|
||||
<script src="/lib/jszip.min.js" defer></script>
|
||||
</head>
|
||||
<body class="dragging bg-base color-base">
|
||||
<div id="app"></div>
|
||||
|
||||
20
package.json
20
package.json
@ -16,8 +16,6 @@
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "esno scripts/prepare.ts",
|
||||
"prebuild": "esno scripts/prebuild.ts",
|
||||
"postbuild": "esno scripts/postbuild.ts",
|
||||
"lint": "eslint .",
|
||||
"dev": "vite --port 3333 --open",
|
||||
"dev-pwa": "SW_DEV=true vite --port 3333",
|
||||
@ -46,34 +44,24 @@
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"client-zip": "^2.5.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-format": "^1.0.1",
|
||||
"esno": "^4.8.0",
|
||||
"fast-glob": "^3.3.3",
|
||||
"fs-extra": "^11.3.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lru-cache": "^11.0.2",
|
||||
"pnpm": "^10.6.5",
|
||||
"shiki": "^3.2.1",
|
||||
"svg-packer": "^0.0.3",
|
||||
"svg-packer": "^1.0.0",
|
||||
"typescript": "^5.8.2",
|
||||
"unocss": "^66.1.0-beta.6",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.2",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-pages": "^0.32.5",
|
||||
"vite-plugin-pwa": "^0.21.2",
|
||||
"vite-plugin-pwa": "^1.0.0",
|
||||
"vue-tsc": "^2.2.8"
|
||||
},
|
||||
"pnpm": {
|
||||
"neverBuiltDependencies": [
|
||||
"electron",
|
||||
"electron-builder",
|
||||
"ttf2woff2",
|
||||
"vite-plugin-electron",
|
||||
"vite-plugin-electron-renderer",
|
||||
"vite-plugin-esmodule"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
1717
pnpm-lock.yaml
generated
1717
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,4 @@
|
||||
packages:
|
||||
- electron
|
||||
onlyBuiltDependencies:
|
||||
- ttf2woff2
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { promises as fs } from 'node:fs'
|
||||
|
||||
;
|
||||
|
||||
(async () => {
|
||||
const path = './dist/index.html'
|
||||
const file = await fs.readFile(path, 'utf-8')
|
||||
await fs.writeFile(path, file.replace(/\/\/lib/g, '/lib'), 'utf-8')
|
||||
})()
|
||||
|
||||
;(async () => {
|
||||
const path = './index.html'
|
||||
const file = await fs.readFile(path, 'utf-8')
|
||||
await fs.writeFile(path, file.replace(/\/\/lib/g, '/lib'), 'utf-8')
|
||||
})()
|
||||
@ -1,9 +0,0 @@
|
||||
import { promises as fs } from 'node:fs'
|
||||
|
||||
;
|
||||
|
||||
(async () => {
|
||||
const path = './index.html'
|
||||
const file = await fs.readFile(path, 'utf-8')
|
||||
await fs.writeFile(path, file.replace(/\/lib/g, '//lib'), 'utf-8')
|
||||
})()
|
||||
@ -77,23 +77,4 @@ async function prepareJSON() {
|
||||
await fs.writeJSON(path.join(infoOut, 'collections-info.json'), collections)
|
||||
}
|
||||
|
||||
async function copyLibs() {
|
||||
const modules = path.resolve(__dirname, '../node_modules')
|
||||
|
||||
await fs.copy(
|
||||
path.join(modules, 'svg-packer/dist/index.browser.js'),
|
||||
path.join(out, 'lib/svg-packer.js'),
|
||||
)
|
||||
|
||||
await fs.copy(
|
||||
path.join(modules, 'jszip/dist/jszip.min.js'),
|
||||
path.join(out, 'lib/jszip.min.js'),
|
||||
)
|
||||
}
|
||||
|
||||
async function prepare() {
|
||||
await copyLibs()
|
||||
await prepareJSON()
|
||||
}
|
||||
|
||||
prepare()
|
||||
prepareJSON()
|
||||
|
||||
3
src/shims.d.ts
vendored
3
src/shims.d.ts
vendored
@ -1,7 +1,4 @@
|
||||
interface Window {
|
||||
JSZip: import('jszip')
|
||||
SvgPacker: (options: any) => Promise<any>
|
||||
|
||||
// for vscode
|
||||
baseURI?: string
|
||||
staticURI?: string
|
||||
|
||||
@ -23,6 +23,29 @@ export async function LoadIconSvgs(icons: string[]) {
|
||||
)
|
||||
}
|
||||
|
||||
export async function* PrepareIconSvgs(icons: string[], format: 'svg' | 'json', name?: string) {
|
||||
if (format === 'json') {
|
||||
const svgs = await LoadIconSvgs(icons)
|
||||
yield {
|
||||
name: `${name}.json`,
|
||||
input: new Blob([JSON.stringify(svgs, null, 2)], { type: 'application/json; charset=utf-8' }),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for (const icon of icons) {
|
||||
if (!icon)
|
||||
continue
|
||||
|
||||
const svg = await getSvg(icon)
|
||||
|
||||
yield {
|
||||
name: `${normalizeZipFleName(icon)}.svg`,
|
||||
input: new Blob([svg], { type: 'image/svg+xml' }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function Download(blob: Blob, name: string) {
|
||||
if (isVSCode) {
|
||||
blob.arrayBuffer().then(
|
||||
@ -62,11 +85,19 @@ ${symbols}
|
||||
Download(blob, 'sprite.svg')
|
||||
}
|
||||
|
||||
function normalizeZipFleName(svgName: string): string {
|
||||
return svgName.replace(':', '-')
|
||||
}
|
||||
|
||||
export async function PackIconFont(icons: string[], options: any = {}) {
|
||||
if (!icons.length)
|
||||
return
|
||||
const data = await LoadIconSvgs(icons)
|
||||
const result = await window.SvgPacker({
|
||||
|
||||
const [data, { SvgPacker }] = await Promise.all([
|
||||
LoadIconSvgs(icons),
|
||||
import('svg-packer'),
|
||||
])
|
||||
const result = await SvgPacker({
|
||||
fontName: 'Iconify Explorer Font',
|
||||
fileName: 'iconfont',
|
||||
cssPrefix: 'i',
|
||||
@ -80,32 +111,67 @@ export async function PackIconFont(icons: string[], options: any = {}) {
|
||||
export async function PackSvgZip(icons: string[], name: string) {
|
||||
if (!icons.length)
|
||||
return
|
||||
const data = await LoadIconSvgs(icons)
|
||||
|
||||
const zip = new window.JSZip()
|
||||
for (const { name, svg } of data)
|
||||
zip.file(`${name}.svg`, svg)
|
||||
|
||||
const blob = await zip.generateAsync({ type: 'blob' })
|
||||
Download(blob, `${name}.zip`)
|
||||
Download(
|
||||
await import('client-zip').then(({ downloadZip }) => downloadZip(
|
||||
PrepareIconSvgs(icons, 'svg'),
|
||||
).blob()),
|
||||
`${name}.zip`,
|
||||
)
|
||||
}
|
||||
|
||||
export async function PackJsonZip(icons: string[], name: string) {
|
||||
if (!icons.length)
|
||||
return
|
||||
const data = await LoadIconSvgs(icons)
|
||||
|
||||
const zip = new window.JSZip()
|
||||
zip.file(`${name}.json`, JSON.stringify(data, null, 2))
|
||||
|
||||
const blob = await zip.generateAsync({ type: 'blob' })
|
||||
Download(blob, `${name}.zip`)
|
||||
Download(
|
||||
await import('client-zip').then(({ downloadZip }) => downloadZip(
|
||||
PrepareIconSvgs(icons, 'json', name),
|
||||
).blob()),
|
||||
`${name}.zip`,
|
||||
)
|
||||
}
|
||||
|
||||
export type PackType = 'svg' | 'tsx' | 'jsx' | 'vue' | 'json'
|
||||
|
||||
function normalizeZipFleName(svgName: string): string {
|
||||
return svgName.replace(':', '-')
|
||||
async function* PreparePackZip(
|
||||
icons: string[],
|
||||
name: string,
|
||||
type: PackType,
|
||||
) {
|
||||
if (type === 'json' || type === 'svg') {
|
||||
yield* PrepareIconSvgs(icons, type, name)
|
||||
return
|
||||
}
|
||||
|
||||
for (const name of icons) {
|
||||
if (!name)
|
||||
continue
|
||||
|
||||
const svg = await getSvg(name)
|
||||
|
||||
const componentName = toComponentName(normalizeZipFleName(name))
|
||||
let content: string
|
||||
|
||||
switch (type) {
|
||||
case 'vue':
|
||||
content = await SvgToVue(svg, componentName)
|
||||
break
|
||||
case 'jsx':
|
||||
content = await SvgToJSX(svg, componentName, false)
|
||||
break
|
||||
case 'tsx':
|
||||
content = await SvgToTSX(svg, componentName, false)
|
||||
break
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
yield {
|
||||
name: `${componentName}.${type}`,
|
||||
input: new Blob([content], { type: 'text/plain' }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function PackZip(
|
||||
@ -115,39 +181,11 @@ export async function PackZip(
|
||||
) {
|
||||
if (!icons.length)
|
||||
return
|
||||
const data = await LoadIconSvgs(icons)
|
||||
|
||||
const zip = new window.JSZip()
|
||||
|
||||
const zipActions: Record<PackType, (name: string, svg: string) => void | (() => void)> = {
|
||||
vue(name: string, svg: string) {
|
||||
name = toComponentName(name)
|
||||
zip.file(`${name}.vue`, SvgToVue(svg, name))
|
||||
},
|
||||
jsx(name: string, svg: string) {
|
||||
name = toComponentName(name)
|
||||
zip.file(`${name}.jsx`, SvgToJSX(svg, name, false))
|
||||
},
|
||||
tsx(name: string, svg: string) {
|
||||
name = toComponentName(name)
|
||||
zip.file(`${name}.tsx`, SvgToTSX(svg, name, false))
|
||||
},
|
||||
svg(name: string, svg: string) {
|
||||
zip.file(`${name}.svg`, svg)
|
||||
},
|
||||
json() {
|
||||
zip.file(`${name}.json`, JSON.stringify(data, null, 2))
|
||||
},
|
||||
}
|
||||
|
||||
const action = zipActions[type]
|
||||
if (type === 'json') {
|
||||
(action as () => void)()
|
||||
}
|
||||
else {
|
||||
for (const { name, svg } of data)
|
||||
action(normalizeZipFleName(name), svg)
|
||||
}
|
||||
const blob = await zip.generateAsync({ type: 'blob' })
|
||||
Download(blob, `${name}-${type}.zip`)
|
||||
Download(
|
||||
await import('client-zip').then(({ downloadZip }) => downloadZip(
|
||||
PreparePackZip(icons, name, type),
|
||||
).blob()),
|
||||
`${name}-${type}.zip`,
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import process from 'node:process'
|
||||
import Vue from '@vitejs/plugin-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import fg from 'fast-glob'
|
||||
import { SvgPackerVitePlugin } from 'svg-packer/vite'
|
||||
import UnoCSS from 'unocss/vite'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
@ -61,6 +62,7 @@ export default defineConfig(({ mode }) => {
|
||||
],
|
||||
dts: 'src/auto-imports.d.ts',
|
||||
}),
|
||||
SvgPackerVitePlugin(),
|
||||
!isElectron && VitePWA({
|
||||
strategies: 'injectManifest',
|
||||
srcDir: 'src',
|
||||
@ -83,7 +85,8 @@ export default defineConfig(({ mode }) => {
|
||||
],
|
||||
},
|
||||
injectManifest: {
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
// collections-meta.json ~7.5MB
|
||||
maximumFileSizeToCacheInBytes: 10 * 1024 * 1024,
|
||||
},
|
||||
integration: {
|
||||
configureOptions(viteConfig, options) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user