mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-07-22 04:40:17 +03:00
feat: инициализировать пакет генерации SVG-спрайтов
- создан NPM-пакет @gromlab/svg-sprites (ESM, TypeScript) - реализован CLI через citty и программный API - добавлена компиляция SVG в спрайты (stack/symbol) через svg-sprite - добавлена генерация TypeScript union-типов имён иконок - реализованы SVG-трансформации: замена цветов на CSS-переменные, удаление width/height, добавление transition к элементам с цветом - добавлен генератор HTML-превью с color picker-ами, авто-темой, синхронизацией currentColor с темой и поиском по иконкам - добавлены тестовые SVG-файлы (icons, logos)
This commit is contained in:
85
src/compiler.ts
Normal file
85
src/compiler.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import SVGSpriter from 'svg-sprite'
|
||||
import { createShapeTransform } from './transforms.js'
|
||||
import type { SpriteFolder, SpriteMode, TransformOptions } from './types.js'
|
||||
|
||||
/** Конфигурация режима для svg-sprite. */
|
||||
function getModeConfig(mode: SpriteMode, destDir: string) {
|
||||
return {
|
||||
dest: destDir,
|
||||
sprite: `sprite.${mode}.svg`,
|
||||
example: false,
|
||||
rootviewbox: false,
|
||||
}
|
||||
}
|
||||
|
||||
/** Строит массив shape.transform на основе опций. */
|
||||
function buildShapeTransforms(transform: TransformOptions) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const transforms: any[] = ['svgo']
|
||||
|
||||
const hasCustomTransform =
|
||||
transform.removeSize !== false ||
|
||||
transform.replaceColors !== false ||
|
||||
transform.addTransition !== false
|
||||
|
||||
if (hasCustomTransform) {
|
||||
transforms.push(createShapeTransform(transform))
|
||||
}
|
||||
|
||||
return transforms
|
||||
}
|
||||
|
||||
/**
|
||||
* Компилирует папку с SVG-файлами в спрайт.
|
||||
*
|
||||
* Возвращает путь к сгенерированному SVG-файлу.
|
||||
*/
|
||||
export async function compileSprite(
|
||||
folder: SpriteFolder,
|
||||
outputDir: string,
|
||||
transform: TransformOptions = {},
|
||||
): Promise<string> {
|
||||
const destDir = path.join(outputDir, folder.name)
|
||||
|
||||
const config = {
|
||||
shape: {
|
||||
transform: buildShapeTransforms(transform),
|
||||
},
|
||||
mode: {
|
||||
[folder.mode]: getModeConfig(folder.mode, destDir),
|
||||
},
|
||||
}
|
||||
|
||||
const spriter = new SVGSpriter(config)
|
||||
|
||||
for (const filePath of folder.files) {
|
||||
spriter.add(filePath, null, fs.readFileSync(filePath, 'utf-8'))
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
spriter.compile((error, result) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
return
|
||||
}
|
||||
|
||||
let spritePath = ''
|
||||
|
||||
for (const modeResult of Object.values(result)) {
|
||||
for (const resource of Object.values(
|
||||
modeResult as Record<string, { path: string; contents: Buffer }>,
|
||||
)) {
|
||||
fs.mkdirSync(path.dirname(resource.path), { recursive: true })
|
||||
fs.writeFileSync(resource.path, resource.contents)
|
||||
if (resource.path.endsWith('.svg')) {
|
||||
spritePath = resource.path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolve(spritePath)
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user