mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-07-22 04:40:17 +03:00
sync
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
Для настройки выберите guide одного exact mode. Каждый guide является
|
||||
самостоятельным документом и без изменений используется в AI skills.
|
||||
|
||||
Общий формат JSON, JavaScript и TypeScript config-файлов описан в [руководстве по конфигурации](configuration.md).
|
||||
|
||||
## Гайды быстрого старта
|
||||
|
||||
| Проект | Exact mode | Guide |
|
||||
@@ -20,10 +22,11 @@
|
||||
Все guides используют один порядок:
|
||||
|
||||
1. Генерация спрайта через `npx` без добавления package в проект.
|
||||
2. Необязательное подключение Viewer для дебага и превью.
|
||||
3. Необязательная типизация конфига через package или локальный copy-paste type.
|
||||
2. Использование спрайта в приложении.
|
||||
3. Необязательное подключение Viewer для дебага и превью.
|
||||
|
||||
## Справочники
|
||||
|
||||
- [Конфигурация](configuration.md)
|
||||
- [Технический справочник](reference/technical.md)
|
||||
- [Программный API](reference/programmatic-api.md)
|
||||
|
||||
99
docs/ru/configuration.md
Normal file
99
docs/ru/configuration.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Конфигурация
|
||||
|
||||
Каждый config-файл описывает один независимый спрайт. CLI не ищет конфиг автоматически, поэтому всегда передавайте путь явно:
|
||||
|
||||
```bash
|
||||
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json
|
||||
```
|
||||
|
||||
## JSON
|
||||
|
||||
JSON подходит для большинства проектов и не требует локальной установки пакета:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "next@app/turbopack",
|
||||
"name": "app",
|
||||
"description": "Общие иконки приложения",
|
||||
"input": [
|
||||
"./icons",
|
||||
"../../assets/icons/**/*.svg",
|
||||
"!../../assets/icons/deprecated-*.svg"
|
||||
],
|
||||
"transform": {
|
||||
"removeSize": true,
|
||||
"replaceColors": true,
|
||||
"addTransition": true
|
||||
},
|
||||
"generatedNotice": true
|
||||
}
|
||||
```
|
||||
|
||||
| Поле | По умолчанию | Назначение |
|
||||
|---|---|---|
|
||||
| `mode` | Нет | Exact mode, соответствующий framework и сборщику |
|
||||
| `name` | Kebab-case имени каталога модуля; для `svg-sprite` и `svg-sprites` — имени родительского каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и типов |
|
||||
| `description` | Нет | Описание для типов и Viewer |
|
||||
| `input` | `./icons` | Каталог, SVG-файл, glob-шаблон или массив источников |
|
||||
| `transform` | Все включены | Настройки подготовки SVG |
|
||||
| `generatedNotice` | `true` | Вид предупреждения в generated-файлах |
|
||||
|
||||
Пути и glob-шаблоны в `input` считаются от каталога config-файла. Паттерн с префиксом `!` исключает совпадения.
|
||||
|
||||
## JavaScript
|
||||
|
||||
JavaScript-конфиг экспортирует обычный объект по умолчанию:
|
||||
|
||||
```js
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
input: './icons',
|
||||
}
|
||||
```
|
||||
|
||||
Передайте CLI путь к `.js`-файлу так же, как к JSON:
|
||||
|
||||
```bash
|
||||
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.js
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
Для проверки конфига TypeScript установите пакет как dev dependency:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Используйте `defineSpriteConfig`:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
input: './icons',
|
||||
})
|
||||
```
|
||||
|
||||
Или примените `satisfies` с type-only импортом:
|
||||
|
||||
```ts
|
||||
import type { SpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
input: './icons',
|
||||
} satisfies SpriteConfig
|
||||
```
|
||||
|
||||
CLI загружает `.ts`-конфиг напрямую:
|
||||
|
||||
```bash
|
||||
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Полный список modes, CLI-флагов, правил именования и transform-опций находится в [техническом справочнике](reference/technical.md).
|
||||
78
docs/ru/guides/AGENTS.md
Normal file
78
docs/ru/guides/AGENTS.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Правила гайдов быстрого старта
|
||||
|
||||
## Цель
|
||||
|
||||
Гайд должен помочь читателю как можно быстрее создать SVG-спрайт и использовать его в своём приложении.
|
||||
|
||||
Спрайт является главным результатом. Компоненты и другие сгенерированные файлы описываются только как средства его использования.
|
||||
|
||||
## Область гайда
|
||||
|
||||
Каждый гайд посвящён одному exact mode.
|
||||
|
||||
В гайд включаются только действия и особенности, относящиеся к этому mode. Нельзя переносить в него поведение других сборщиков, фреймворков или modes.
|
||||
|
||||
Все технические утверждения необходимо проверять по реализации соответствующего adapter.
|
||||
|
||||
## Структура
|
||||
|
||||
Гайд состоит из трёх основных частей:
|
||||
|
||||
1. Генерация спрайта.
|
||||
2. Использование спрайта.
|
||||
3. Дебаг и превью через Viewer.
|
||||
|
||||
Первая строка после заголовка должна объяснять, что это инструкция по быстрому созданию SVG-спрайта и для какого приложения она предназначена.
|
||||
|
||||
## Примеры
|
||||
|
||||
Все примеры внутри гайда должны составлять один последовательный сценарий.
|
||||
|
||||
Пути, имена, команды, импорты и названия сгенерированных API должны соответствовать друг другу и фактическому результату генерации.
|
||||
|
||||
Во всех гайдах используются согласованные примеры:
|
||||
|
||||
- исходные SVG находятся в `assets/svg-icons`;
|
||||
- спрайт создаётся в `assets/app-icons`;
|
||||
- конфиг записывается в JSON;
|
||||
- имя спрайта в конфиге — `app`.
|
||||
|
||||
## Зависимости
|
||||
|
||||
В разделе генерации нужно явно показать ключевое преимущество: для создания и использования спрайта пакет не требуется добавлять в зависимости проекта.
|
||||
|
||||
Viewer описывается отдельно как необязательный инструмент разработки. Установка или подключение пакета допускается только в разделе Viewer и только способом, подходящим текущему mode.
|
||||
|
||||
## Содержание
|
||||
|
||||
Гайд должен содержать только минимальный рабочий путь:
|
||||
|
||||
- структуру проекта;
|
||||
- конфиг;
|
||||
- команду генерации;
|
||||
- автоматическую генерацию перед запуском и сборкой, если она необходима;
|
||||
- подключение иконки;
|
||||
- базовую настройку размера и цветов;
|
||||
- подключение Viewer.
|
||||
|
||||
Особенности mode добавляются только тогда, когда без них пример не работает или работает неправильно.
|
||||
|
||||
## Технический шум
|
||||
|
||||
Не нужно описывать внутреннее устройство генератора, сгенерированных файлов и сборщика.
|
||||
|
||||
Не нужно перечислять альтернативные конфигурации, дополнительные API, редкие сценарии и ограничения, не относящиеся к быстрому старту.
|
||||
|
||||
Подробности должны оставаться в reference-документации.
|
||||
|
||||
## Стиль
|
||||
|
||||
Писать для пользователя, а не для разработчика библиотеки.
|
||||
|
||||
Использовать короткие, прямые и практические формулировки.
|
||||
|
||||
Сначала объяснять пользу или цель шага, затем показывать действие.
|
||||
|
||||
Не использовать воду, рекламные формулировки и технические термины, которые не помогают выполнить инструкцию.
|
||||
|
||||
Не начинать документ с перечисления сгенерированных компонентов или особенностей реализации.
|
||||
@@ -1,153 +1,108 @@
|
||||
# Next.js App Router с Turbopack
|
||||
# SVG-спрайт для Next.js App Router с Turbopack
|
||||
|
||||
Это автономный quick start для exact mode key `next@app/turbopack`: generated `IconsIcon` совместим с Server Components и asset pipeline Turbopack.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с App Router и Turbopack.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "next@app/turbopack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Конфиг может быть `.ts`, `.js` с `default export` или `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI зафиксируйте точную версию, например `@gromlab/svg-sprites@1.1.5`. Mode и команды Next должны указывать один bundler:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --turbopack",
|
||||
"build": "npm run sprites && next build --turbopack",
|
||||
"start": "next start",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "next dev --turbopack",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "next build --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не добавляйте одновременно `predev`/`prebuild` и явный `npm run sprites`. Generated `.svg-sprite` не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Его `.d.ts` self-contained и не импортируют generator package.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Generated icon не содержит `'use client'`, поэтому его можно импортировать прямо в Server Component:
|
||||
Используйте компонент в Server Component:
|
||||
|
||||
```tsx
|
||||
// app/page.tsx
|
||||
import { IconsIcon, iconsIconNames } from '../src/sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-label="Готово"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
<span>{iconsIconNames.length} иконок</span>
|
||||
</main>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Turbopack обрабатывает generated `new URL('../sprite.svg', import.meta.url).href` и выпускает внешний hashed asset. Не добавляйте Client Component boundary только ради `IconsIcon`.
|
||||
Для `AppIcon` не нужен `'use client'`. Turbopack сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||
|
||||
## 2. Дебаг и превью
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer необязателен и нужен только для debug/preview:
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Viewer интерактивен, поэтому создайте для него отдельный Client Component:
|
||||
Создайте Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||
|
||||
```tsx
|
||||
// app/icons-debug/sprite-viewer.tsx
|
||||
'use client'
|
||||
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export function AppSpriteViewer() {
|
||||
export function SvgSpriteViewer() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
```
|
||||
|
||||
Server page импортирует только эту boundary:
|
||||
Создайте маршрут `app/svg-sprite/page.tsx`:
|
||||
|
||||
```tsx
|
||||
// app/icons-debug/page.tsx
|
||||
import { AppSpriteViewer } from './sprite-viewer'
|
||||
import { notFound } from 'next/navigation'
|
||||
|
||||
export default function IconsDebugPage() {
|
||||
return <AppSpriteViewer />
|
||||
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||
|
||||
export default function SvgSpritePage() {
|
||||
if (process.env.NODE_ENV !== 'development') notFound()
|
||||
|
||||
return <SvgSpriteViewer />
|
||||
}
|
||||
```
|
||||
|
||||
Viewer не входит в production icon runtime и не нужен обычным страницам с `IconsIcon`.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
После локальной установки package используйте helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Возможен и type-only import `SpriteConfig` с `satisfies SpriteConfig`.
|
||||
|
||||
Без package добавьте локальный type в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@app/turbopack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Exact literal защищает от смешивания App Router и других bundler contracts.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||
|
||||
@@ -1,151 +1,108 @@
|
||||
# Next.js App Router с Webpack
|
||||
# SVG-спрайт для Next.js App Router с Webpack
|
||||
|
||||
Это автономный quick start для exact mode key `next@app/webpack`: generated `IconsIcon` совместим с Server Components и Webpack pipeline Next.js.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с App Router и Webpack.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "next@app/webpack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Также поддерживаются `.js` с `default export` и `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI замените `latest` точной версией, например `@gromlab/svg-sprites@1.1.5`. Exact Next commands для этого mode:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --webpack",
|
||||
"build": "npm run sprites && next build --webpack",
|
||||
"start": "next start",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "next dev --webpack",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "next build --webpack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не сочетайте явный `npm run sprites` с `predev` или `prebuild`. `.svg-sprite` generated и не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated declarations self-contained и не зависят от `@gromlab/svg-sprites`.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage в Server Component:
|
||||
Используйте компонент в Server Component:
|
||||
|
||||
```tsx
|
||||
// app/page.tsx
|
||||
import { IconsIcon, iconsIconNames } from '../src/sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-label="Готово"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
<span>{iconsIconNames.length} иконок</span>
|
||||
</main>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Generated component не содержит `'use client'`. Next Webpack обрабатывает `new URL('../sprite.svg', import.meta.url).href` и публикует отдельный SVG asset; не переписывайте этот URL и не переносите sprite в `public` вручную.
|
||||
Для `AppIcon` не нужен `'use client'`. Next.js сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||
|
||||
## 2. Дебаг и превью
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer необязателен. Для debug/preview установите package:
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
App Router требует отдельную Client Component boundary для Viewer:
|
||||
Создайте Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||
|
||||
```tsx
|
||||
// app/icons-debug/sprite-viewer.tsx
|
||||
'use client'
|
||||
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export function AppSpriteViewer() {
|
||||
export function SvgSpriteViewer() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
```
|
||||
|
||||
Создайте маршрут `app/svg-sprite/page.tsx`:
|
||||
|
||||
```tsx
|
||||
// app/icons-debug/page.tsx
|
||||
import { AppSpriteViewer } from './sprite-viewer'
|
||||
import { notFound } from 'next/navigation'
|
||||
|
||||
export default function IconsDebugPage() {
|
||||
return <AppSpriteViewer />
|
||||
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||
|
||||
export default function SvgSpritePage() {
|
||||
if (process.env.NODE_ENV !== 'development') notFound()
|
||||
|
||||
return <SvgSpriteViewer />
|
||||
}
|
||||
```
|
||||
|
||||
Статический loader позволяет Webpack связать manifest и emitted SVG. Viewer не входит в production runtime `IconsIcon`.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
При локально установленном package используйте helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Другой package-вариант: type-only import `SpriteConfig` и `satisfies SpriteConfig`.
|
||||
|
||||
Без package вставьте локальный type прямо в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@app/webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@app/webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Локальный exact literal исключает случайную генерацию Turbopack или Pages Router output.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||
|
||||
@@ -1,140 +1,98 @@
|
||||
# Next.js Pages Router с Turbopack
|
||||
# SVG-спрайт для Next.js Pages Router с Turbopack
|
||||
|
||||
Это автономный quick start для exact mode key `next@pages/turbopack`: generated `IconsIcon` работает при SSR, SSG и клиентских переходах Pages Router.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с Pages Router и Turbopack.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "next@pages/turbopack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Конфиг также может быть `.js` с `default export` или `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Для CI зафиксируйте точную версию, например `@gromlab/svg-sprites@1.1.5`. Exact commands должны сохранять Turbopack и для dev, и для production build:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --turbopack",
|
||||
"build": "npm run sprites && next build --turbopack",
|
||||
"start": "next start",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "next dev --turbopack",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "next build --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не добавляйте `predev`/`prebuild`, если scripts уже явно вызывают `npm run sprites`. Generated `.svg-sprite` не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated `.d.ts` self-contained и не импортируют generator package.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage на обычной page:
|
||||
Используйте компонент на странице:
|
||||
|
||||
```tsx
|
||||
// pages/index.tsx
|
||||
import { IconsIcon, iconsIconNames } from '../src/sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-label="Готово"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
<span>{iconsIconNames.length} иконок</span>
|
||||
</main>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Компонент одинаково работает с `getServerSideProps`, `getStaticProps` и client navigation. Turbopack разрешает generated `new URL('../sprite.svg', import.meta.url).href` в отдельный hashed asset.
|
||||
Компонент работает с SSR, SSG и клиентскими переходами. Turbopack сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||
|
||||
## 2. Дебаг и превью
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer необязателен и нужен только для debug/preview:
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
В Pages Router Viewer можно использовать прямо в page, без отдельной App Router Client Component boundary:
|
||||
Создайте страницу `pages/svg-sprite.tsx`:
|
||||
|
||||
```tsx
|
||||
// pages/icons-debug.tsx
|
||||
import type { GetStaticProps } from 'next'
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export default function IconsDebugPage() {
|
||||
export default function SvgSpritePage() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps = () =>
|
||||
process.env.NODE_ENV === 'development'
|
||||
? { props: {} }
|
||||
: { notFound: true }
|
||||
```
|
||||
|
||||
Оставляйте эту page только во внутреннем debug-разделе. Viewer не входит в production icon runtime `IconsIcon`.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
Если package установлен локально, используйте helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Альтернатива: type-only import `SpriteConfig` и объект `satisfies SpriteConfig`.
|
||||
|
||||
Без package добавьте copy-paste type в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@pages/turbopack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@pages/turbopack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Exact literal не позволяет незаметно смешать Pages Router с App Router или Webpack output.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||
|
||||
@@ -1,140 +1,98 @@
|
||||
# Next.js Pages Router с Webpack
|
||||
# SVG-спрайт для Next.js Pages Router с Webpack
|
||||
|
||||
Это автономный quick start для exact mode key `next@pages/webpack`: generated `IconsIcon` работает в Pages Router и публикует SVG через Webpack pipeline Next.js.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с Pages Router и Webpack.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "next@pages/webpack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Поддерживаются `.ts`, `.js` с `default export` и `.json` configs.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI замените `latest` на точную проверенную версию, например `@gromlab/svg-sprites@1.1.5`. Exact Next commands для Webpack:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && next dev --webpack",
|
||||
"build": "npm run sprites && next build --webpack",
|
||||
"start": "next start",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "next dev --webpack",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "next build --webpack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не дублируйте эти вызовы через `predev`, `prebuild` или `pretypecheck`. `.svg-sprite` generated и не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated declarations self-contained и не требуют `@gromlab/svg-sprites`.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage:
|
||||
Используйте компонент на странице:
|
||||
|
||||
```tsx
|
||||
// pages/index.tsx
|
||||
import { IconsIcon, iconsIconNames } from '../src/sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<main>
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-label="Готово"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
<span>{iconsIconNames.length} иконок</span>
|
||||
</main>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Компонент поддерживает SSR, SSG и клиентские переходы. Next Webpack преобразует generated `new URL('../sprite.svg', import.meta.url).href` во внешний hashed asset; не конструируйте URL спрайта вручную.
|
||||
Компонент работает с SSR, SSG и клиентскими переходами. Next.js сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||
|
||||
## 2. Дебаг и превью
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer необязателен. Устанавливайте package только для debug/preview:
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Pages Router позволяет разместить Viewer непосредственно в page без отдельной App Router boundary:
|
||||
Создайте страницу `pages/svg-sprite.tsx`:
|
||||
|
||||
```tsx
|
||||
// pages/icons-debug.tsx
|
||||
import type { GetStaticProps } from 'next'
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export default function IconsDebugPage() {
|
||||
export default function SvgSpritePage() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps = () =>
|
||||
process.env.NODE_ENV === 'development'
|
||||
? { props: {} }
|
||||
: { notFound: true }
|
||||
```
|
||||
|
||||
Статический loader даёт Webpack точный manifest module и связанный SVG asset. Не импортируйте Viewer из production pages, если preview там не нужен; runtime `IconsIcon` от него независим.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
После локальной установки package доступен helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Также можно применить `satisfies SpriteConfig` с type-only импортом `SpriteConfig`.
|
||||
|
||||
Без package вставьте локальный type прямо в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'next@pages/webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Такой exact literal выявляет ошибочный выбор App Router или Turbopack ещё при проверке config.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||
|
||||
@@ -1,141 +1,115 @@
|
||||
# React-компонент для Vite
|
||||
# SVG-спрайт для React на Vite
|
||||
|
||||
Это автономный quick start для exact mode key `react@vite`: генератор создаёт типизированный `IconsIcon`, а Vite публикует отдельный SVG asset.
|
||||
Инструкция по быстрому созданию SVG-спрайта в React-приложении на Vite.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "react@vite",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Вместо `.ts` можно использовать `.js` с `default export` или `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI замените `latest` на точную версию, например `@gromlab/svg-sprites@1.1.5`. Exact Vite commands:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && vite",
|
||||
"build": "npm run sprites && tsc --noEmit && vite build",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "vite",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "tsc --noEmit && vite build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не добавляйте `predev`, `prebuild` или `pretypecheck`, если соответствующие scripts уже явно запускают `npm run sprites`. Generated `.svg-sprite` не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated declarations self-contained: они описывают компонент и manifest без импорта `@gromlab/svg-sprites`.
|
||||
## Использование спрайта
|
||||
|
||||
Пользовательский barrel возвращает generated API:
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage:
|
||||
Используйте компонент в приложении:
|
||||
|
||||
```tsx
|
||||
import { IconsIcon, iconsIconNames } from './sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export function SaveButton() {
|
||||
export function SaveIcon() {
|
||||
return (
|
||||
<button type="button">
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-hidden="true"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
Сохранить
|
||||
</button>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
console.log(iconsIconNames)
|
||||
```
|
||||
|
||||
Prop `icon` является union имён исходных файлов. Vite автоматически обрабатывает generated CSS Module и импорт `sprite.svg?no-inline`; query запрещает inline и заставляет Vite выпустить отдельный hashed SVG asset. Если TypeScript не знает Vite asset imports, добавьте `/// <reference types="vite/client" />` в `src/vite-env.d.ts`.
|
||||
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||
|
||||
## 2. Дебаг и превью
|
||||
Vite сам подключает стили компонента и добавляет `sprite.svg` в итоговую сборку.
|
||||
|
||||
Viewer необязателен и нужен только для debug/preview. Установите package отдельно:
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Используйте React bridge со статическим массивом loaders:
|
||||
Создайте `svg-sprite.html` в корне проекта:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Иконки проекта</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- React-корень Viewer для дебага и превью SVG-спрайта -->
|
||||
<div id="svg-sprite-viewer"></div>
|
||||
|
||||
<!-- Подключение создаваемого ниже скрипта дебаггера -->
|
||||
<script type="module" src="/src/svg-sprite-debug.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Создайте `src/svg-sprite-debug.tsx`:
|
||||
|
||||
```tsx
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export function IconsDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
createRoot(document.getElementById('svg-sprite-viewer')!).render(
|
||||
<SpriteViewer sources={sources} title="Иконки проекта" />,
|
||||
)
|
||||
```
|
||||
|
||||
Строковый путь в `import()` должен указывать на generated JS manifest. Держите страницу за debug-маршрутом; `SpriteViewer` не входит в production runtime `IconsIcon`.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite.html`.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
Если package установлен локально, используйте helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Также можно импортировать `SpriteConfig` только как type и написать объект `satisfies SpriteConfig`.
|
||||
|
||||
Без package добавьте локальный type прямо в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'react@vite'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'react@vite',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Локальный type проверяет только этот exact mode и не создаёт runtime-зависимость.
|
||||
Стандартная production-сборка Vite использует только `index.html` и не включает страницу Viewer.
|
||||
|
||||
@@ -1,141 +1,126 @@
|
||||
# React-компонент для Webpack 5
|
||||
# SVG-спрайт для React на Webpack 5
|
||||
|
||||
Это автономный quick start для exact mode key `react@webpack`: generated `IconsIcon` использует Webpack 5 Asset Modules и CSS Modules.
|
||||
Инструкция по быстрому созданию SVG-спрайта в React-приложении на Webpack 5.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "react@webpack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Поддерживаются `.ts`, `.js` с `default export` и `.json` configs.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI замените `latest` на точную версию, например `@gromlab/svg-sprites@1.1.5`. Exact Webpack commands:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && webpack serve --mode development",
|
||||
"build": "npm run sprites && webpack --mode production",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "webpack serve --mode development",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "webpack --mode production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не сочетайте эти явные вызовы с `predev`/`prebuild`: иначе генерация задублируется. `.svg-sprite` не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated `.d.ts` self-contained и не импортируют generator package.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage:
|
||||
Используйте компонент в приложении:
|
||||
|
||||
```tsx
|
||||
import { IconsIcon, iconsIconNames } from './sprite'
|
||||
import { AppIcon } from '../assets/app-icons'
|
||||
|
||||
export function SaveButton() {
|
||||
export function SaveIcon() {
|
||||
return (
|
||||
<button type="button">
|
||||
<IconsIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
aria-hidden="true"
|
||||
style={{ '--icon-color-1': '#16a34a' }}
|
||||
/>
|
||||
Сохранить
|
||||
</button>
|
||||
<AppIcon
|
||||
icon="check"
|
||||
width={24}
|
||||
height={24}
|
||||
role="img"
|
||||
aria-label="Готово"
|
||||
style={{
|
||||
color: '#334155',
|
||||
'--icon-color-2': '#f59e0b',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
console.log(iconsIconNames)
|
||||
```
|
||||
|
||||
Generated component получает URL через `new URL('../sprite.svg', import.meta.url).href`. Webpack 5 должен обработать SVG как Asset Module. Исключите generated `sprite.svg` из `@svgr/webpack`, inline/raw loaders и других общих SVG rules либо задайте для него `type: 'asset/resource'`.
|
||||
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||
|
||||
Компонент импортирует `react-component.module.css`. Webpack config должен обрабатывать `*.module.css` через `css-loader` с CSS Modules и `style-loader` или `MiniCssExtractPlugin`. Для TypeScript при необходимости добавьте декларацию `declare module '*.module.css'`.
|
||||
Компонент использует CSS Modules. Если проект ещё не обрабатывает их с default export, добавьте правило в `webpack.config.js`:
|
||||
|
||||
## 2. Дебаг и превью
|
||||
```js
|
||||
{
|
||||
test: /\.module\.css$/i,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: { modules: { namedExport: false } },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Viewer необязателен. Устанавливайте package только для debug/preview:
|
||||
Webpack 5 сам добавляет `sprite.svg` в итоговую сборку.
|
||||
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки.
|
||||
|
||||
Установите Viewer:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Webpack не использует `import.meta.glob`; передайте статический loader:
|
||||
Создайте entry `src/svg-sprite-debug.tsx`:
|
||||
|
||||
```tsx
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
] as const
|
||||
|
||||
export function IconsDebugPage() {
|
||||
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||
}
|
||||
const container = document.createElement('div')
|
||||
document.body.append(container)
|
||||
|
||||
createRoot(container).render(
|
||||
<SpriteViewer sources={sources} title="Иконки проекта" />,
|
||||
)
|
||||
```
|
||||
|
||||
Webpack создаст chunk manifest и разрешит его SVG через тот же Asset Modules pipeline. Viewer держите только в debug route; production `IconsIcon` от него не зависит.
|
||||
Добавьте скрипт к основному entry только в development-режиме. Сохраните остальные настройки `webpack.config.js`:
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
С локально установленным package доступен helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
```js
|
||||
export default (_env, argv) => ({
|
||||
// Остальные настройки Webpack.
|
||||
entry: [
|
||||
'./src/main.tsx',
|
||||
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.tsx'] : []),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
Эквивалентная проверка: type-only import `SpriteConfig` и `satisfies SpriteConfig`.
|
||||
|
||||
Без package используйте copy-paste type в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'react@webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'react@webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Локальный literal не разрешит случайно выбрать Vite или Next mode.
|
||||
Запустите `npm run dev`. Viewer появится на основной странице приложения и не попадёт в production-сборку.
|
||||
|
||||
@@ -1,151 +1,114 @@
|
||||
# Нативный icon Web Component с Vite
|
||||
# SVG-спрайт для Vite без фреймворка
|
||||
|
||||
Это автономный quick start для exact mode key `standalone@vite`: generated facade регистрирует `<icons-icon>` и отдаёт SVG в asset pipeline Vite.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении на Vite без фреймворка.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
Рекомендуемая структура держит конфиг и иконки рядом:
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Минимальный plain config:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "standalone@vite",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Конфиг также может быть `.js` с `default export` или `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
В CI замените `latest` на точную версию, например `@gromlab/svg-sprites@1.1.5`. Exact dev/build commands для Vite:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && vite",
|
||||
"build": "npm run sprites && vite build",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "vite",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "vite build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не добавляйте одновременно `predev`/`prebuild` и явный `npm run sprites` в этих scripts. `.svg-sprite` является generated-каталогом и не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Generated `.d.ts` self-contained и не импортируют `@gromlab/svg-sprites`.
|
||||
## Использование спрайта
|
||||
|
||||
Верните facade через пользовательский barrel:
|
||||
Значение `name: "app"` создаёт элемент `<app-icon>`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production entry регистрирует native Web Component:
|
||||
Зарегистрируйте элемент в `src/main.ts`:
|
||||
|
||||
```ts
|
||||
import { defineIconsIconElement, iconsIconNames } from './sprite'
|
||||
import { defineAppIconElement } from '../assets/app-icons'
|
||||
import './style.css'
|
||||
|
||||
defineIconsIconElement()
|
||||
|
||||
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
|
||||
<icons-icon icon="check" role="img" aria-label="Готово"></icons-icon>
|
||||
`
|
||||
|
||||
console.log(iconsIconNames)
|
||||
defineAppIconElement()
|
||||
```
|
||||
|
||||
Generated facade импортирует `sprite.svg?no-inline`: Vite автоматически выпускает отдельный hashed SVG asset и не превращает его в data URL. TypeScript-проекту при необходимости добавьте стандартные Vite types:
|
||||
Используйте иконку в HTML:
|
||||
|
||||
```ts
|
||||
/// <reference types="vite/client" />
|
||||
```html
|
||||
<app-icon icon="check" role="img" aria-label="Готово"></app-icon>
|
||||
```
|
||||
|
||||
Размер по умолчанию равен `1em`, поэтому компонент удобно масштабировать через `font-size`. Цвет задаётся через `color` и generated custom properties:
|
||||
Файл `check.svg` доступен как `icon="check"`. Размер и цвета настраиваются через CSS:
|
||||
|
||||
```css
|
||||
icons-icon {
|
||||
app-icon {
|
||||
font-size: 24px;
|
||||
color: #334155;
|
||||
--icon-color-2: #f59e0b;
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Дебаг и превью
|
||||
Монохромная иконка наследует `color`, а цвета многоцветной иконки переопределяются через `--icon-color-N`. Нужные переменные показывает Viewer.
|
||||
|
||||
Viewer необязателен и нужен только для debug/preview. Установите его отдельно:
|
||||
Vite сам добавит `sprite.svg` в итоговую сборку. Копировать его в `public` не нужно.
|
||||
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Зарегистрируйте Viewer и передайте generated JS manifest через свойство `sources`:
|
||||
Создайте `svg-sprite.html` в корне проекта:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Иконки проекта</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Компонент Viewer для дебага и превью SVG-спрайта -->
|
||||
<gromlab-sprite-viewer viewer-title="Иконки проекта"></gromlab-sprite-viewer>
|
||||
|
||||
<!-- Подключение создаваемого ниже скрипта дебаггера -->
|
||||
<script type="module" src="/src/svg-sprite-debug.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Создайте `src/svg-sprite-debug.ts`:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
document.querySelector<HTMLDivElement>('#app')!.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
'<gromlab-sprite-viewer></gromlab-sprite-viewer>',
|
||||
)
|
||||
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
viewer.viewerTitle = 'Иконки проекта'
|
||||
viewer.sources = [spriteManifest]
|
||||
```
|
||||
|
||||
Расположите этот код только в debug entry или внутреннем маршруте. Viewer не входит в production runtime `<icons-icon>`.
|
||||
Запустите `npm run dev` и откройте `/svg-sprite.html`.
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
При локально установленном package используйте helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
})
|
||||
```
|
||||
|
||||
Альтернатива с package: `import type { SpriteConfig }` и объект `satisfies SpriteConfig`.
|
||||
|
||||
Без package скопируйте локальный type прямо в config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'standalone@vite'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'standalone@vite',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Локальный type ограничивает `mode` одним exact literal и ничего не загружает во время генерации.
|
||||
Viewer не требуется для работы `<app-icon>` и не подключается к основному коду приложения.
|
||||
|
||||
@@ -1,145 +1,111 @@
|
||||
# Нативный icon Web Component с Webpack 5
|
||||
# SVG-спрайт для Webpack 5 без фреймворка
|
||||
|
||||
Это автономный quick start для exact mode key `standalone@webpack`: generated facade предоставляет `<icons-icon>`, а Webpack 5 публикует SVG через Asset Modules.
|
||||
Инструкция по быстрому созданию SVG-спрайта в приложении на Webpack 5 без фреймворка.
|
||||
|
||||
## 1. Генерация спрайта
|
||||
## Генерация спрайта
|
||||
|
||||
Главное преимущество: генератор не нужно устанавливать и добавлять в `package.json`. `npx` временно скачивает CLI, а generated production runtime не импортирует `@gromlab/svg-sprites`.
|
||||
Выберите папку для спрайта. В примере используется `assets/app-icons`, а исходные SVG находятся в `assets/svg-icons`.
|
||||
|
||||
```text
|
||||
src/sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── warning.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
Создайте конфиг `assets/app-icons/svg-sprite.config.json`:
|
||||
|
||||
Минимальный config рядом с `icons/`:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
```json
|
||||
{
|
||||
"mode": "standalone@webpack",
|
||||
"name": "app",
|
||||
"input": "../svg-icons/**/*.svg"
|
||||
}
|
||||
```
|
||||
|
||||
Если `input` не указан, SVG читаются из `./icons` относительно конфига. Поддерживаются также `.js` с `default export` и `.json`.
|
||||
Путь в `input` считается от папки с конфигом.
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts
|
||||
```
|
||||
|
||||
Для CI закрепите точную версию, например `@gromlab/svg-sprites@1.1.5`. Exact Webpack commands:
|
||||
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/sprite/svg-sprite.config.ts",
|
||||
"dev": "npm run sprites && webpack serve --mode development",
|
||||
"build": "npm run sprites && webpack --mode production",
|
||||
"typecheck": "npm run sprites && tsc --noEmit"
|
||||
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||
"predev": "npm run sprites",
|
||||
"dev": "webpack serve --mode development",
|
||||
"prebuild": "npm run sprites",
|
||||
"build": "webpack --mode production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не дублируйте запуск через `predev`/`prebuild`, если scripts уже явно вызывают `npm run sprites`. Generated `.svg-sprite` не коммитится. Generated локальный `.gitignore`, который исключает этот каталог, нужно добавить в Git один раз. Его declarations self-contained и не требуют `@gromlab/svg-sprites`.
|
||||
## Использование спрайта
|
||||
|
||||
Значение `name: "app"` создаёт элемент `<app-icon>`.
|
||||
|
||||
Создайте точку входа `assets/app-icons/index.ts`:
|
||||
|
||||
```ts
|
||||
// src/sprite/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Production usage:
|
||||
Зарегистрируйте элемент в основном entry приложения:
|
||||
|
||||
```ts
|
||||
import { defineIconsIconElement, iconsIconNames } from './sprite'
|
||||
import { defineAppIconElement } from '../assets/app-icons'
|
||||
import './style.css'
|
||||
|
||||
defineIconsIconElement()
|
||||
|
||||
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
|
||||
<icons-icon icon="check" role="img" aria-label="Готово"></icons-icon>
|
||||
`
|
||||
|
||||
console.log(iconsIconNames)
|
||||
defineAppIconElement()
|
||||
```
|
||||
|
||||
Generated facade использует `new URL('./sprite.svg', import.meta.url).href`. Webpack 5 Asset Modules выпускают отдельный asset; его итоговый URL учитывает `output.publicPath` и `assetModuleFilename`.
|
||||
Используйте иконку в HTML:
|
||||
|
||||
Если проект использует `@svgr/webpack`, `svg-inline-loader`, `raw-loader` или общий SVG rule, исключите `src/sprite/.svg-sprite/sprite.svg` из этого правила. Generated SVG должен обрабатываться как `asset/resource`, а не как React-компонент или inline source.
|
||||
```html
|
||||
<app-icon icon="check" role="img" aria-label="Готово"></app-icon>
|
||||
```
|
||||
|
||||
Размер Web Component по умолчанию `1em`; управляйте им и цветами обычным CSS:
|
||||
Файл `check.svg` доступен как `icon="check"`. Размер и цвета настраиваются через CSS:
|
||||
|
||||
```css
|
||||
icons-icon {
|
||||
app-icon {
|
||||
font-size: 24px;
|
||||
color: #334155;
|
||||
--icon-color-2: #f59e0b;
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Дебаг и превью
|
||||
Монохромная иконка наследует `color`, а цвета многоцветной иконки переопределяются через `--icon-color-N`. Нужные переменные показывает Viewer.
|
||||
|
||||
Viewer необязателен. Для debug/preview установите package как dev dependency:
|
||||
Webpack 5 сам добавит `sprite.svg` в итоговую сборку.
|
||||
|
||||
## Дебаг и превью
|
||||
|
||||
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки.
|
||||
|
||||
Установите Viewer:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
Подключите element entry и generated JS manifest:
|
||||
Создайте entry `src/svg-sprite-debug.ts`:
|
||||
|
||||
```ts
|
||||
import '@gromlab/svg-sprites/viewer/element'
|
||||
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||
|
||||
document.querySelector<HTMLDivElement>('#app')!.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
'<gromlab-sprite-viewer></gromlab-sprite-viewer>',
|
||||
)
|
||||
|
||||
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||
viewer.viewerTitle = 'Иконки проекта'
|
||||
viewer.sources = [spriteManifest]
|
||||
document.body.append(viewer)
|
||||
```
|
||||
|
||||
Webpack свяжет manifest с тем же emitted SVG asset. Оставляйте Viewer только в debug entry: production `<icons-icon>` от него не зависит.
|
||||
Добавьте скрипт к основному entry только в development-режиме. Сохраните остальные настройки `webpack.config.js`:
|
||||
|
||||
## 3. Типизация конфига
|
||||
|
||||
После локальной установки package можно использовать helper:
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
```js
|
||||
export default (_env, argv) => ({
|
||||
// Остальные настройки Webpack.
|
||||
entry: [
|
||||
'./src/main.ts',
|
||||
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.ts'] : []),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
Либо импортируйте только `SpriteConfig` как type и примените `satisfies SpriteConfig`.
|
||||
Запустите `npm run dev`. Viewer появится на основной странице приложения.
|
||||
|
||||
Без package добавьте copy-paste type в сам config:
|
||||
|
||||
```ts
|
||||
type LocalSpriteConfig = {
|
||||
mode: 'standalone@webpack'
|
||||
name?: string
|
||||
description?: string
|
||||
input?: string | string[]
|
||||
transform?: {
|
||||
removeSize?: boolean
|
||||
replaceColors?: boolean
|
||||
addTransition?: boolean
|
||||
}
|
||||
generatedNotice?: boolean
|
||||
}
|
||||
|
||||
export default {
|
||||
mode: 'standalone@webpack',
|
||||
name: 'icons',
|
||||
} satisfies LocalSpriteConfig
|
||||
```
|
||||
|
||||
Этот вариант сохраняет проверку exact mode без runtime import и без записи generator package в проект.
|
||||
Viewer добавляется только в development-сборку и не попадает в production.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Guides Next.js App Router перемещены
|
||||
|
||||
- [App Router + Turbopack](guides/next-app-turbopack.md)
|
||||
- [App Router + Webpack](guides/next-app-webpack.md)
|
||||
@@ -1,4 +0,0 @@
|
||||
# Guides Next.js Pages Router перемещены
|
||||
|
||||
- [Pages Router + Turbopack](guides/next-pages-turbopack.md)
|
||||
- [Pages Router + Webpack](guides/next-pages-webpack.md)
|
||||
@@ -1,3 +0,0 @@
|
||||
# Программный API перемещён
|
||||
|
||||
Canonical документ: [программный API](reference/programmatic-api.md).
|
||||
@@ -1,3 +0,0 @@
|
||||
# Guide React + Vite перемещён
|
||||
|
||||
Canonical guide: [React + Vite](guides/react-vite.md).
|
||||
@@ -1,3 +0,0 @@
|
||||
# Guide React + Webpack перемещён
|
||||
|
||||
Canonical guide: [React + Webpack](guides/react-webpack.md).
|
||||
@@ -1,3 +0,0 @@
|
||||
# Технический справочник перемещён
|
||||
|
||||
Canonical документ: [технический справочник](reference/technical.md).
|
||||
@@ -14,6 +14,21 @@ const result = await generateSprite(
|
||||
)
|
||||
```
|
||||
|
||||
Результат содержит имя и mode спрайта, количество иконок и абсолютные filesystem paths:
|
||||
|
||||
```ts
|
||||
result.name
|
||||
result.mode
|
||||
result.target
|
||||
result.iconCount
|
||||
result.rootDir
|
||||
result.generatedDir
|
||||
result.spritePath
|
||||
result.manifestPath
|
||||
```
|
||||
|
||||
Next.js modes дополнительно возвращают `router` и `bundler`.
|
||||
|
||||
Для static standalone mode `result.spritePath` можно использовать в build-скрипте,
|
||||
чтобы опубликовать SVG по URL приложения:
|
||||
|
||||
@@ -29,7 +44,7 @@ await copyFile(result.spritePath, 'dist/app-icons/sprite.svg')
|
||||
`spritePath` является filesystem path, а не browser URL. Deployment-neutral JSON
|
||||
manifest доступен через `result.manifestPath` и копируется независимо от SVG.
|
||||
|
||||
Первый аргумент принимает полный путь к config-файлу с любым именем и расширением `.ts`, `.js` или `.json`. Каталог вместо файла включает config-less режим: корнем sprite-модуля становится этот каталог.
|
||||
Первый аргумент принимает абсолютный или относительный путь к config-файлу с любым именем и расширением `.ts`, `.js` или `.json`. Каталог вместо файла включает config-less режим: корнем sprite-модуля становится этот каталог.
|
||||
|
||||
Второй аргумент содержит необязательные overrides и всегда имеет приоритет над конфигом:
|
||||
|
||||
@@ -107,13 +122,17 @@ await generateNextSprite('path/to/config.ts', {
|
||||
|
||||
```ts
|
||||
import {
|
||||
isSpriteMode,
|
||||
loadSpriteConfig,
|
||||
resolveSpriteConfig,
|
||||
resolveSpriteConfigSource,
|
||||
validateSpriteConfig,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
- `isSpriteMode(value)` проверяет, является ли значение поддерживаемым exact mode.
|
||||
- `loadSpriteConfig(file)` загружает явно указанный `.ts`, `.js` или `.json` файл.
|
||||
- `resolveSpriteConfigSource(source)` разрешает путь как config-файл или config-less каталог.
|
||||
- `validateSpriteConfig(value)` выполняет runtime-валидацию объекта.
|
||||
- `resolveSpriteConfig(root, config, overrides)` объединяет значения, добавляет defaults и разрешает пути относительно `root`.
|
||||
|
||||
@@ -138,6 +157,16 @@ import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
|
||||
Browser entry регистрирует `<gromlab-sprite-viewer>`. Bare standalone также может загрузить самостоятельный `dist/viewer-element.js` без bundler.
|
||||
|
||||
Для ручной регистрации импортируйте runtime без auto-register entry:
|
||||
|
||||
```ts
|
||||
import { defineSpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||
|
||||
defineSpriteViewerElement()
|
||||
```
|
||||
|
||||
Этот entry также экспортирует типы `SpriteViewerElement`, `SpriteViewerManifest`, `SpriteViewerSource`, `SpriteViewerSources` и связанные типы manifest и loaders.
|
||||
|
||||
React bridge сохраняет компонентный API:
|
||||
|
||||
```tsx
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
[Индекс документации](../README.md)
|
||||
|
||||
[Конфигурация JSON, JavaScript и TypeScript](../configuration.md)
|
||||
|
||||
Справочник по конфигурации, generated API и поведению `@gromlab/svg-sprites`. Пошаговую установку смотрите в руководстве для вашего стека:
|
||||
|
||||
- [Bare standalone](../guides/standalone.md)
|
||||
@@ -24,7 +26,7 @@
|
||||
Для генерации не нужна dependency проекта. Запускайте CLI через `npx`:
|
||||
|
||||
```bash
|
||||
npx --yes --package=@gromlab/svg-sprites@latest svg-sprites path/to/svg-sprite.config.ts
|
||||
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json
|
||||
```
|
||||
|
||||
Устанавливайте пакет как development dependency, только если проекту нужны
|
||||
@@ -36,7 +38,7 @@ npm install --save-dev @gromlab/svg-sprites
|
||||
|
||||
## CLI и режимы генерации
|
||||
|
||||
CLI принимает ровно один путь: явно выбранный config-файл либо каталог для config-less генерации:
|
||||
Для генерации CLI принимает ровно один путь: явно выбранный config-файл либо каталог для config-less генерации:
|
||||
|
||||
```text
|
||||
svg-sprites [options] <config-file-or-directory>
|
||||
@@ -54,11 +56,11 @@ svg-sprites [options] <config-file-or-directory>
|
||||
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||
|
||||
Config-файл может иметь любое имя и расширение `.ts`, `.js` или `.json`. CLI не ищет конфиг по соглашению: файл нужно передать явно. В руководствах используется рекомендуемое имя `svg-sprite.config.ts`.
|
||||
Config-файл может иметь любое имя и расширение `.ts`, `.js` или `.json`. CLI не ищет конфиг по соглашению: файл нужно передать явно. В руководствах используется рекомендуемое имя `svg-sprite.config.json`.
|
||||
|
||||
Если передан каталог, все настройки берутся из CLI. Если передан config-файл, CLI-параметры перекрывают значения файла. Общий порядок: `defaults → config → CLI`.
|
||||
|
||||
Доступны `--mode`, `--name`, `--description`, повторяемый `--input <path-or-glob>`, а также пары `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition` и `--generated-notice`/`--no-generated-notice`. Переданные transform-флаги перекрывают отдельные поля, а хотя бы один `--input` полностью заменяет значение `input` из config.
|
||||
`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--name`, `--description`, повторяемый `--input <path-or-glob>`, а также пары `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition` и `--generated-notice`/`--no-generated-notice`. Переданные transform-флаги перекрывают отдельные поля, а хотя бы один `--input` полностью заменяет значение `input` из config.
|
||||
|
||||
В CLI заключайте glob-паттерны в одинарные кавычки, чтобы shell не раскрыл их до запуска генератора:
|
||||
|
||||
@@ -96,7 +98,7 @@ export default defineSpriteConfig({
|
||||
| Опция | Тип | По умолчанию | Назначение |
|
||||
|---|---|---|---|
|
||||
| `mode` | `SpriteMode` | Нет | Режим генерации; можно передать через CLI/API |
|
||||
| `name` | `string` | Выводится из каталога | Имя спрайта, компонента и публичных типов |
|
||||
| `name` | `string` | Выводится из каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и публичных типов |
|
||||
| `description` | `string` | Нет | Описание для типов и debug manifest |
|
||||
| `input` | `string \| string[]` | `./icons` | Папки, SVG-файлы и glob-паттерны относительно папки конфига |
|
||||
| `transform` | `TransformOptions` | Все включены | Настройки подготовки SVG |
|
||||
@@ -111,7 +113,7 @@ app → AppIcon
|
||||
file-manager → FileManagerIcon
|
||||
```
|
||||
|
||||
Если `name` не задано, генератор выводит его из каталога. Для каталога с именем `svg-sprite` или `svg-sprites` используется имя родительского каталога.
|
||||
Если `name` не задано, генератор преобразует имя каталога в kebab-case. Для каталога с именем `svg-sprite` или `svg-sprites` используется имя родительского каталога.
|
||||
|
||||
### Источники иконок
|
||||
|
||||
@@ -141,7 +143,7 @@ file-manager → FileManagerIcon
|
||||
```text
|
||||
app-icons/
|
||||
├── .gitignore
|
||||
├── svg-sprite.config.ts
|
||||
├── svg-sprite.config.json
|
||||
├── index.ts # необязательный пользовательский barrel
|
||||
└── .svg-sprite/
|
||||
├── index.js
|
||||
@@ -183,10 +185,10 @@ runtime asset и deployment-neutral manifest data:
|
||||
generated Web Component без внешних runtime-зависимостей. Bare `standalone`
|
||||
намеренно не создаёт JavaScript-компонент.
|
||||
|
||||
Генератор перезаписывает и удаляет только файлы со своим marker. Если в managed-пути находится пользовательский файл, генерация завершается ошибкой. Корневой `index.ts` генератору не принадлежит; при необходимости создайте пользовательский barrel:
|
||||
`.svg-sprite` полностью управляется генератором и при каждой генерации заменяется целиком. Любые добавленные в него файлы будут удалены. Пользовательские файлы размещайте рядом, например в корневом `index.ts`:
|
||||
|
||||
```ts
|
||||
export * from './.svg-sprite'
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
## Standalone Web Component и TypeScript
|
||||
@@ -307,7 +309,7 @@ folder open.svg → icon="folder open" → id="icon-<stable-hash>"
|
||||
|
||||
## Множественные спрайты
|
||||
|
||||
Каждый каталог с конфигом создаёт независимый компонент, типы, manifest и SVG asset:
|
||||
Каждый каталог с конфигом создаёт независимый mode-specific контракт. React и Next.js создают React-компонент и типы, `standalone@vite` и `standalone@webpack` — Web Component и типы, а bare `standalone` — SVG и JSON manifest:
|
||||
|
||||
```text
|
||||
app-icons → AppIcon → общие иконки
|
||||
@@ -353,7 +355,7 @@ Static HTML после публикации `.svg-sprite/sprite.svg` прило
|
||||
</svg>
|
||||
```
|
||||
|
||||
Standalone Vite/Webpack предоставляет generated `getIconsIconHref()` и mapping
|
||||
Standalone Vite/Webpack предоставляет generated `getAppIconHref()` и mapping
|
||||
внутренних IDs. Не конструируйте fragment из небезопасного имени файла вручную.
|
||||
|
||||
Vite:
|
||||
@@ -602,7 +604,7 @@ Viewer показывает группы, поиск, `viewBox`, CSS-перем
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "npx --yes --package=@gromlab/svg-sprites@latest svg-sprites src/ui/app-icons/svg-sprite.config.ts",
|
||||
"sprites": "npx --yes @gromlab/svg-sprites src/ui/app-icons/svg-sprite.config.ts",
|
||||
"predev": "npm run sprites",
|
||||
"prebuild": "npm run sprites",
|
||||
"pretypecheck": "npm run sprites"
|
||||
@@ -610,22 +612,22 @@ Viewer показывает группы, поиск, `viewBox`, CSS-перем
|
||||
}
|
||||
```
|
||||
|
||||
CI должен выполнять generation script до сборки или проверки типов. Для воспроизводимости замените `latest` на точную версию. Локальная установка package не нужна, если CI не использует Viewer, package-типы config или программный API.
|
||||
CI должен выполнять generation script до сборки или проверки типов. Локальная установка package не нужна, если CI не использует Viewer, package-типы config или программный API.
|
||||
|
||||
Bare `standalone` не создаёт и не изменяет `.gitignore`: приложение само решает, коммитить или игнорировать его `.svg-sprite/`. В остальных modes генератор не перезапишет пользовательский `.gitignore`. Он также откажется перезаписывать пользовательский файл внутри `.svg-sprite`. Корневой `index.ts` остаётся пользовательским и может переэкспортировать generated API.
|
||||
Bare `standalone` не создаёт `.gitignore` и сохраняет пользовательский файл. Если после другого mode остался управляемый `.gitignore`, bare mode удалит его. В остальных modes генератор откажется перезаписать пользовательский `.gitignore` без generated marker. Корневой `index.ts` остаётся пользовательским и может переэкспортировать generated API.
|
||||
|
||||
## Диагностика
|
||||
|
||||
- Нет `.svg-sprite/index.js`: запустите generation script до импорта generated-модуля.
|
||||
- Для всех modes, кроме bare `standalone`: если нет `.svg-sprite/index.js`, запустите generation script до импорта generated-модуля.
|
||||
- Не найден источник: передайте существующий config-файл или каталог sprite-модуля.
|
||||
- Не указан mode: добавьте `mode` в config либо передайте `--mode`.
|
||||
- Иконка отсутствует в типе: проверьте `input`, расширение `.svg`, glob-исключения и необходимость `**/*.svg` для вложенных папок.
|
||||
- Конфликт имени: два разных SVG имеют одинаковый basename; переименуйте один файл.
|
||||
- `Refusing to overwrite a user file`: в managed-пути находится файл без generated marker.
|
||||
- `Refusing to overwrite a user file`: в корне sprite-модуля находится пользовательский `.gitignore`, который генератор не может заменить.
|
||||
- Иконка не меняет цвет: используйте `<svg><use>` или generated-компонент и проверьте `replaceColors`.
|
||||
- Webpack выдаёт неверный URL: проверьте Asset Modules, `output.publicPath` и SVG loaders.
|
||||
- Static sprite возвращает 404: проверьте post-generation copy или server alias и не передавайте filesystem `spritePath` в HTML.
|
||||
- Viewer не видит спрайт: проверьте путь к `.svg-sprite/svg-sprite.manifest.js` и выполните генерацию до запуска приложения.
|
||||
- Viewer не видит спрайт: для bundler modes проверьте путь к `.svg-sprite/svg-sprite.manifest.js`; для bare `standalone` — URL опубликованных `svg-sprite.manifest.json` и `sprite.svg`. Выполните генерацию до запуска приложения.
|
||||
- Build и mode не совпадают: используйте target, соответствующий фактическому сборщику.
|
||||
|
||||
Для собственного orchestration и низкоуровневой компиляции смотрите [Программный API](programmatic-api.md).
|
||||
|
||||
Reference in New Issue
Block a user