mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-09-05 08:20:19 +03:00
feat(skills): добавить установку через npx skills add
This commit is contained in:
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -78,10 +78,10 @@ jobs:
|
|||||||
run: npm pack --ignore-scripts --pack-destination release
|
run: npm pack --ignore-scripts --pack-destination release
|
||||||
|
|
||||||
- name: Pack skills
|
- name: Pack skills
|
||||||
working-directory: skills/artifacts
|
working-directory: skills
|
||||||
run: |
|
run: |
|
||||||
zip -r ../../release/svg-sprites.zip svg-sprites
|
zip -r ../release/svg-sprites.zip svg-sprites
|
||||||
zip -r ../../release/svg-sprites-ru.zip svg-sprites-ru
|
zip -r ../release/svg-sprites-ru.zip svg-sprites-ru
|
||||||
|
|
||||||
- name: Create checksums
|
- name: Create checksums
|
||||||
run: sha256sum release/* > release/SHA256SUMS
|
run: sha256sum release/* > release/SHA256SUMS
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,7 +5,6 @@ test/public/
|
|||||||
test/.next-fixture-*/
|
test/.next-fixture-*/
|
||||||
test-results/
|
test-results/
|
||||||
.tmp/
|
.tmp/
|
||||||
skills/artifacts/
|
|
||||||
*.generated.ts
|
*.generated.ts
|
||||||
*.tgz
|
*.tgz
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -28,9 +28,17 @@ You do not have to work with the sprite directly in your application. Use it lik
|
|||||||
|
|
||||||
`@gromlab/svg-sprites` is designed to work with AI agents from the start. Add the ready-made skill and ask an agent to configure, migrate, or troubleshoot the package without lengthy instructions or manual documentation research.
|
`@gromlab/svg-sprites` is designed to work with AI agents from the start. Add the ready-made skill and ask an agent to configure, migrate, or troubleshoot the package without lengthy instructions or manual documentation research.
|
||||||
|
|
||||||
[🇬🇧 Download AI skill (English)](https://github.com/gromlab-ru/svg-sprites/releases/latest/download/svg-sprites.zip)
|
Install the English skill:
|
||||||
|
|
||||||
[🇷🇺 Download AI skill (Russian)](https://github.com/gromlab-ru/svg-sprites/releases/latest/download/svg-sprites-ru.zip)
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the Russian skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites-ru
|
||||||
|
```
|
||||||
|
|
||||||
## From SVG to component in three steps
|
## From SVG to component in three steps
|
||||||
|
|
||||||
|
|||||||
12
README_RU.md
12
README_RU.md
@@ -28,9 +28,17 @@
|
|||||||
|
|
||||||
`@gromlab/svg-sprites` сразу рассчитан на работу с AI-агентами. Подключите готовый skill и поручите агенту настройку, миграцию или диагностику без длинных инструкций и ручного изучения документации.
|
`@gromlab/svg-sprites` сразу рассчитан на работу с AI-агентами. Подключите готовый skill и поручите агенту настройку, миграцию или диагностику без длинных инструкций и ручного изучения документации.
|
||||||
|
|
||||||
[🇷🇺 Скачать AI skill (на русском)](https://github.com/gromlab-ru/svg-sprites/releases/latest/download/svg-sprites-ru.zip)
|
Установить русскоязычный skill:
|
||||||
|
|
||||||
[🇬🇧 Скачать AI skill (на английском)](https://github.com/gromlab-ru/svg-sprites/releases/latest/download/svg-sprites.zip)
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites-ru
|
||||||
|
```
|
||||||
|
|
||||||
|
Установить англоязычный skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
## От SVG до компонента за три шага
|
## От SVG до компонента за три шага
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@gromlab/svg-sprites",
|
"name": "@gromlab/svg-sprites",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@gromlab/svg-sprites",
|
"name": "@gromlab/svg-sprites",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colorette": "^2.0.20",
|
"colorette": "^2.0.20",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@gromlab/svg-sprites",
|
"name": "@gromlab/svg-sprites",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"description": "Generate external SVG sprites and typed native icon components for modern web frameworks",
|
"description": "Generate external SVG sprites and typed native icon components for modern web frameworks",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
@@ -57,8 +57,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run build:package",
|
"build": "npm run build:package",
|
||||||
"build:package": "tsup && tsup --config tsup.browser.config.ts && tsup --config tsup.viewer.config.ts",
|
"build:package": "tsup && tsup --config tsup.browser.config.ts && tsup --config tsup.viewer.config.ts",
|
||||||
"build:skill": "node skills/svg-sprites/build.mjs",
|
"build:skill": "node src/skills/svg-sprites/build.mjs",
|
||||||
"check:skill": "node skills/svg-sprites/build.mjs --check",
|
"check:skill": "node src/skills/svg-sprites/build.mjs --check",
|
||||||
"dev": "tsup --watch",
|
"dev": "tsup --watch",
|
||||||
"test": "npm run build:package && node --test test/*.test.mjs",
|
"test": "npm run build:package && node --test test/*.test.mjs",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
|
|||||||
359
skills/svg-sprites-ru/SKILL.md
Normal file
359
skills/svg-sprites-ru/SKILL.md
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
---
|
||||||
|
name: svg-sprites-ru
|
||||||
|
description: "Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок."
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Generated from src/skills/svg-sprites/src/ru/SKILL.md. Do not edit manually. -->
|
||||||
|
|
||||||
|
# @gromlab/svg-sprites
|
||||||
|
|
||||||
|
## Что делает пакет
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` — CLI-генератор SVG-спрайтов для пользовательских SVG-файлов. Пакет не содержит собственного набора иконок: он собирает SVG проекта во внешний sprite asset и создаёт типизированный нативный компонент для выбранного exact framework/bundler mode.
|
||||||
|
|
||||||
|
Пакет рассчитан на несколько независимых спрайтов в одном проекте. Каждый явно выбранный config-файл или config-less каталог описывает один спрайт и получает собственные:
|
||||||
|
|
||||||
|
- SVG asset;
|
||||||
|
- mode-specific manifest data;
|
||||||
|
- для всех modes, кроме bare `standalone`, — типы имён и production entry `.svg-sprite/index.js`;
|
||||||
|
- для framework modes — изолированный нативный компонент и declarations;
|
||||||
|
- для `standalone@vite`/`standalone@webpack` — нативный Web Component с явной функцией регистрации;
|
||||||
|
- для bare `standalone` — deployment-neutral JSON manifest без публичного URL.
|
||||||
|
- для `standalone@server` — content-addressed server release с двумя compile profiles и integrity manifest.
|
||||||
|
|
||||||
|
Количество и расположение каталогов определяет проект. Например, `name: 'file-manager'` создаёт `FileManagerIcon`, `FileManagerIconName` и `fileManagerIconNames`, а другой каталог с `name: 'navigation'` создаст отдельный `NavigationIcon`. Это примеры API отдельных спрайтов, а не фиксированные экспорты пакета.
|
||||||
|
|
||||||
|
Generated production runtime и declarations не импортируют `@gromlab/svg-sprites`. Генерация через `npx --yes @gromlab/svg-sprites <path-to-config>` не добавляет package в проект. Устанавливай его как development dependency только для Viewer, package-типов config или программного API.
|
||||||
|
|
||||||
|
Любой consumer exact mode может использовать `source: 'remote'` с одним local path
|
||||||
|
или HTTP(S) URL manifest, созданного `standalone@server`. До запуска adapter генератор
|
||||||
|
скачивает и проверяет нужный profile, после чего создаётся обычный локальный API и
|
||||||
|
asset; в runtime браузер не зависит от server manifest.
|
||||||
|
|
||||||
|
## Выбор режима
|
||||||
|
|
||||||
|
Выбери ровно один поддерживаемый mode key:
|
||||||
|
|
||||||
|
| Проект | Mode key |
|
||||||
|
|---|---|
|
||||||
|
| Static HTML / собственная публикация | `standalone` |
|
||||||
|
| Standalone + Vite | `standalone@vite` |
|
||||||
|
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||||
|
| Server или CI release | `standalone@server` |
|
||||||
|
| React + Vite | `react@vite` |
|
||||||
|
| React + Webpack 5 | `react@webpack` |
|
||||||
|
| Vue + Vite | `vue@vite` |
|
||||||
|
| Vue + Webpack | `vue@webpack` |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` |
|
||||||
|
| Svelte + Vite | `svelte@vite` |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` |
|
||||||
|
| Angular application builder | `angular@application` |
|
||||||
|
| Angular + Webpack | `angular@webpack` |
|
||||||
|
| Astro + Vite | `astro@vite` |
|
||||||
|
| Solid + Vite | `solid@vite` |
|
||||||
|
| Solid + Webpack | `solid@webpack` |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` |
|
||||||
|
| Preact + Vite | `preact@vite` |
|
||||||
|
| Preact + Webpack | `preact@webpack` |
|
||||||
|
| Qwik + Vite | `qwik@vite` |
|
||||||
|
| Lit + Vite | `lit@vite` |
|
||||||
|
| Lit + Webpack | `lit@webpack` |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||||
|
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||||
|
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||||
|
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||||
|
|
||||||
|
Mode задаётся в config, CLI или программном API. Порядок применения: `defaults → config → CLI/API overrides`. После объединения mode обязателен.
|
||||||
|
|
||||||
|
`name` необязателен. Если он не задан, генератор преобразует имя каталога sprite-модуля в kebab-case; для каталогов `svg-sprite` и `svg-sprites` используется имя родительского каталога. Явное `name` должно уже быть записано в kebab-case и начинаться с латинской буквы.
|
||||||
|
|
||||||
|
CLI принимает ровно один путь. Путь к файлу `.ts`, `.js` или `.json` загружает именно этот конфиг независимо от имени. Путь к каталогу включает config-less генерацию, и настройки передаются флагами CLI.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprite:<name>": "npx --yes @gromlab/svg-sprites <path-to-config>",
|
||||||
|
"sprite:<name>:cli": "npx --yes @gromlab/svg-sprites --mode <mode-key> <sprite-directory>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Генерация через `npx` не добавляет package в проект. Не придумывай сокращённые или generic mode keys и не используй удалённый `legacy`: выбери один полный key из таблицы. Bare `standalone` выбирай только когда приложение само публикует SVG, а `standalone@server` — только для централизованного release, используемого во время генерации consumers. Для нескольких спрайтов создай отдельную команду для каждого config-файла или каталога.
|
||||||
|
|
||||||
|
## Инспекция проекта
|
||||||
|
|
||||||
|
До изменений установи фактический контракт проекта:
|
||||||
|
|
||||||
|
1. Прочитай корневой `package.json`, lock-файл и workspace-конфигурацию; определи framework, bundler и существующие команды.
|
||||||
|
2. Найди config-файлы, команды `svg-sprites` и импорты generated-компонентов. Имя конфига произвольное; ориентируйся на переданный CLI путь и поля объекта.
|
||||||
|
3. Определи framework, router при его наличии и фактический bundler по scripts и конфигу. Для Next.js отдельно определи App/Pages Router и сборщик реальных `dev`/`build` команд.
|
||||||
|
4. Проверь существующие `predev`, `prebuild`, `pretypecheck` и агрегирующие scripts. Не перезаписывай их.
|
||||||
|
5. Для нового спрайта выбери целевой каталог, не навязывая конкретный слой или архитектуру приложения.
|
||||||
|
6. Проверь TypeScript и alias-настройки. Для package subpath exports нужен TypeScript 5+ с `moduleResolution: 'bundler'`, `'node16'` или `'nodenext'`.
|
||||||
|
|
||||||
|
Для обычного local consumer все input-пути считаются относительно каталога, содержащего явно переданный config-файл; в config-less режиме — относительно переданного каталога. Проверяй local `input` по этому контракту:
|
||||||
|
|
||||||
|
- `input?: string | string[]` по умолчанию равен `./icons`;
|
||||||
|
- каждая строка задаёт папку, точный SVG-файл или glob;
|
||||||
|
- папка сканируется плоско; вложенные файлы включаются только явным recursive glob, например `./icons/**/*.svg`;
|
||||||
|
- массив объединяет positive-источники, а элемент с префиксом `!` исключает свои совпадения из общего набора;
|
||||||
|
- каждый positive-источник должен разрешаться хотя бы в один SVG, поэтому отсутствующая или пустая папка, glob без совпадений, отсутствующий файл или точный путь не к SVG являются ошибкой;
|
||||||
|
- разрешённые файлы дедуплицируются и детерминированно сортируются;
|
||||||
|
- разные файлы с одинаковым basename конфликтуют, даже если получены из разных источников.
|
||||||
|
|
||||||
|
До применения этих правил выбери нужную ветку:
|
||||||
|
|
||||||
|
- `standalone@server` может объединять local strings и HTTP(S) descriptors `{ name, url, sha256? }`; `name` задаёт публичное имя иконки, а необязательный `sha256` проверяет скачанные байты;
|
||||||
|
- `source: 'remote'` требует ровно одну строку с local path или HTTP(S) URL manifest и не принимает source globs или descriptors;
|
||||||
|
- remote consumer config содержит только `mode`, `source` и `input`; name, description, transforms и generated notice приходят из проверенного server manifest.
|
||||||
|
|
||||||
|
Не копируй общий SVG в несколько папок: добавь его точный путь или подходящий glob в `input` каждого нужного спрайта. Используй `**/*.svg` только для намеренного рекурсивного включения.
|
||||||
|
|
||||||
|
## Настройка интеграции
|
||||||
|
|
||||||
|
Не воспроизводи настройку mode по памяти. После инспекции проекта выбери один exact mode и открой соответствующий файл из `references/docs/ru/guides/`. Используй guide как базовый рабочий контракт, затем адаптируй его к существующей структуре проекта.
|
||||||
|
|
||||||
|
Работай в таком порядке:
|
||||||
|
|
||||||
|
1. Определи каталог исходных SVG и каталог одного sprite-модуля. Один config создаёт один независимый спрайт; для нескольких наборов нужны отдельные config-файлы и уникальные `name`.
|
||||||
|
2. Сверь framework, router и bundler с exact mode. Для Next.js проверяй реальные `dev` и `build` scripts, а не только наличие `next.config.*`.
|
||||||
|
3. Предпочитай JSON-конфиг, если проекту не нужны package-типы config. TypeScript-конфиг также загружается через CLI, но установка package нужна, когда он импортирует `defineSpriteConfig` или типы.
|
||||||
|
4. Разрешай все `input` относительно каталога config-файла. Не меняй структуру SVG без необходимости: используй путь к папке, точный файл, glob или массив этих источников.
|
||||||
|
5. Добавь sprite-команду с явным путём к config. Сохрани существующие `dev`, `build`, `typecheck` и lifecycle hooks; встрой генерацию до первого процесса, импортирующего `.svg-sprite`.
|
||||||
|
6. Не запускай одну генерацию дважды через одновременный `predev` и `npm run sprites && ...`. Для нескольких спрайтов создай отдельные команды и один агрегирующий script.
|
||||||
|
7. Если приложение импортирует каталог sprite-модуля, создай пользовательский `index.ts` рядом с `.svg-sprite`; не помещай пользовательские файлы внутрь generated-каталога.
|
||||||
|
8. Выполни первую генерацию до typecheck или запуска приложения, затем проверь mode-specific output и фактический импорт компонента.
|
||||||
|
|
||||||
|
Для централизованного release открой `references/docs/ru/guides/standalone-server.md`.
|
||||||
|
Генерируй и публикуй весь каталог `.svg-sprite` атомарно. В каждом consumer сохрани
|
||||||
|
его собственный exact framework mode, укажи `source: 'remote'` и направь `input` на
|
||||||
|
manifest. Не копируй server files во framework output и не загружай manifest из
|
||||||
|
runtime приложения.
|
||||||
|
|
||||||
|
Не добавляй Viewer автоматически. Подключай его только по запросу пользователя или когда нужна визуальная проверка набора, цветов либо сложных SVG. Способ изоляции Viewer от production бери из exact guide: frameworks, bundlers и routers используют разные границы.
|
||||||
|
|
||||||
|
Не копируй snippets между exact modes даже при похожем API. Различаются asset URL, generated-файлы, CSS handling, router boundary и способ подключения debug-инструментов.
|
||||||
|
|
||||||
|
## Контракт generated-каталога
|
||||||
|
|
||||||
|
Например, после генерации React/Next-каталог имеет следующий вид:
|
||||||
|
|
||||||
|
```text
|
||||||
|
svg-sprite/
|
||||||
|
├── icons/ # пользовательские исходники
|
||||||
|
├── svg-sprite.config.json # рекомендуемое имя конфига
|
||||||
|
├── index.ts # необязательный пользовательский barrel
|
||||||
|
├── .gitignore # управляет генератор
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── index.js
|
||||||
|
├── index.d.ts
|
||||||
|
├── icon-data.js
|
||||||
|
├── icon-data.d.ts
|
||||||
|
├── sprite.svg
|
||||||
|
├── svg-sprite.manifest.js
|
||||||
|
├── svg-sprite.manifest.d.ts
|
||||||
|
└── react/
|
||||||
|
├── react-component.js
|
||||||
|
├── react-component.d.ts
|
||||||
|
└── react-component.module.css
|
||||||
|
```
|
||||||
|
|
||||||
|
Standalone не создаёт `react/`. Bare `standalone` генерирует `sprite.svg` и `svg-sprite.manifest.json`; `standalone@vite`/`standalone@webpack` дополнительно генерируют `index.*`, `icon-data.*` и resolved manifest. Их `index.*` также содержит нативный generated Web Component; bare `standalone` не получает JS runtime и не создаёт `.gitignore`.
|
||||||
|
|
||||||
|
`standalone@server` генерирует `sprite.<content-hash>.svg`,
|
||||||
|
`sprite-root-viewbox.<content-hash>.svg` и `svg-sprite.manifest.json`. У него нет
|
||||||
|
consumer facade, browser runtime, Viewer entry или `.gitignore`. Manifest хранит
|
||||||
|
relative URL обоих profiles, полные SHA-256, размеры в байтах, metadata иконок и
|
||||||
|
настройки transforms.
|
||||||
|
|
||||||
|
Редактируй исходные SVG, config-файл и пользовательский `index.ts`. Не изменяй вручную содержимое `.svg-sprite`: повторная генерация его перезапишет. Во всех modes, кроме bare `standalone`, generated `.gitignore` также находится под управлением генератора. Для импорта из корня sprite-модуля создай barrel:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Генератор полностью владеет каталогом `.svg-sprite` и заменяет его при каждом запуске. Никогда не помещай туда пользовательские файлы. Генератор также владеет `.gitignore`, когда выбранный mode его создаёт. Bare `standalone` сохраняет пользовательский `.gitignore`, но удаляет управляемый `.gitignore`, оставшийся после другого mode. Generated-пути не должны содержать symlink.
|
||||||
|
|
||||||
|
Каждый exact-mode adapter владеет facade, framework-каталогом, runtime нативного компонента, declarations, manifest source, styles и asset URL. React/Next используют `react/`; остальные framework modes используют собственный generated-контракт из соответствующего guide. Standalone bundler modes экспортируют Web Component helpers и типы, а bare `standalone` не создаёт facade. Manifest declarations объявляют типы локально и не импортируют generator package.
|
||||||
|
|
||||||
|
В bundler modes спрайт остаётся отдельным asset, а SVG path-данные не встраиваются в JavaScript. Content hash зависит от настроек сборщика. Bare `standalone` создаёт файл с фиксированным именем, а приложение само определяет его публичное имя и версионирование:
|
||||||
|
|
||||||
|
- Vite-based adapters используют mode-owned static asset import, сохраняющий sprite внешним;
|
||||||
|
- `standalone@vite` использует тот же Vite asset-механизм и экспортирует href helper и нативный Web Component без React;
|
||||||
|
- `standalone@webpack` использует Webpack Asset Modules и экспортирует такой же mode-local Web Component без React;
|
||||||
|
- Webpack-based adapters и все Next modes используют adapter-owned механизм внешнего asset, обычно `new URL(..., import.meta.url).href`;
|
||||||
|
- кастомный Webpack SVG loader не должен перехватывать generated `sprite.svg`;
|
||||||
|
- в Next mode generated-компонент не содержит `'use client'` и работает в Server Components, SSR и SSG; не добавляй клиентскую границу только ради иконки;
|
||||||
|
- команда сборки Next и mode key должны совпадать: Turbopack с `.../turbopack`, Webpack с `.../webpack`.
|
||||||
|
- remote consumers всё равно публикуются через локальный asset pipeline своего adapter; не сохраняй и не собирай URL server profile в generated application code.
|
||||||
|
|
||||||
|
Для bundler modes не перемещай generated sprite в `public` и не переписывай URL вручную. Для bare `standalone` не перемещай managed original: приложение может явно копировать его в deploy output и само отвечает за публичный URL и очистку копии. При смене mode перегенерируй спрайт с новым полным key.
|
||||||
|
|
||||||
|
## Использование, доступность и цвета
|
||||||
|
|
||||||
|
Имя компонента зависит от `name` конкретного спрайта. В `standalone@vite` и `standalone@webpack` значение `name: 'file-manager'` создаёт tag `<file-manager-icon>` и функцию `defineFileManagerIconElement()`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineFileManagerIconElement } from './svg-sprite'
|
||||||
|
|
||||||
|
defineFileManagerIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<file-manager-icon icon="folder" aria-hidden="true"></file-manager-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
Нативный элемент не имеет runtime-зависимостей, сам выбирает generated ID и `viewBox`, получает URL через bundler и рендерит `<svg><use>` в Shadow DOM. Его property `icon` типизирован точным union имён, но строковые HTML attributes проверяются только в runtime. Размер по умолчанию равен `1em × 1em`; меняй его через CSS на host. Bare `standalone` Web Component не генерирует.
|
||||||
|
|
||||||
|
В component modes тот же `name: 'file-manager'` создаёт нативный компонент `FileManagerIcon`; его синтаксис и props определяет exact-mode guide. В React/Next.js значение `name: 'navigation'` создаёт `NavigationIcon`.
|
||||||
|
|
||||||
|
Импортируй компонент из корня соответствующего каталога спрайта. `width` и `height` не обязательны: размером можно управлять обычным CSS-классом.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { FileManagerIcon } from './svg-sprite'
|
||||||
|
|
||||||
|
export const OpenButton = () => (
|
||||||
|
<button type="button">
|
||||||
|
<FileManagerIcon icon="folder" className="icon" aria-hidden="true" />
|
||||||
|
<span>Открыть</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: #4b5563;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`icon` принимает точные имена исходных файлов без `.svg`; неизвестное имя является ошибкой TypeScript. Для небезопасных SVG ID имён генератор хранит публичное имя, но создаёт внутренний стабильный hash ID, поэтому не собирай fragment URL из имени вручную.
|
||||||
|
|
||||||
|
По умолчанию компонент рендерит `<svg>` и принимает стандартные SVG attributes: необязательные `width`/`height`, `className`, `style`, `role`, `aria-*` и обработчики. С `wrapped={true}` корнем становится `<span>`, props относятся к span, а внутренний SVG занимает размер wrapper.
|
||||||
|
|
||||||
|
Generated-компонент не выбирает семантику за приложение и не добавляет `title`. Для декоративной иконки передай `aria-hidden="true"`; для самостоятельной смысловой иконки передай `role="img"` и доступное имя через `aria-label`. Не дублируй имя, если соседний текст уже озвучивает действие. Интерактивность размещай на `button` или `a`, а не на самой иконке.
|
||||||
|
|
||||||
|
Трансформации `removeSize`, `replaceColors` и `addTransition` включены по умолчанию. Для монохромной иконки единственный цвет получает fallback `currentColor`, поэтому управляй CSS-свойством `color`. Для многоцветной передавай типизированные custom properties:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon
|
||||||
|
icon="folder"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#4b5563',
|
||||||
|
'--icon-color-2': '#14b8a6',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Автозамена рассчитана на `fill`/`stroke` attributes и inline `style`. Значения `none`, `transparent`, `inherit`, `unset`, `initial` не заменяются. CSS-классы и внешние stylesheets, gradients, patterns, filters и `url(#...)` проверяй на реальном результате. Переменные страницы работают через `<svg><use>`, но не проникают во внешний документ при `<img>` или `background-image`; CSS mask оставляет только одноцветный силуэт.
|
||||||
|
|
||||||
|
`SpriteViewer` необязателен. Установи `@gromlab/svg-sprites` как development dependency, только если проекту нужен Viewer. Он принимает manifests или статически обнаружимые loaders, показывает поиск, темы, цвета и примеры, но production-компоненты от него не зависят.
|
||||||
|
|
||||||
|
Перед подключением Viewer открой exact guide. Frameworks, bundlers и routers требуют разных debug entries или client boundaries. Не переноси способ подключения между modes.
|
||||||
|
|
||||||
|
## Проверка результата
|
||||||
|
|
||||||
|
После изменения конфига или SVG выполни обязательные проверки:
|
||||||
|
|
||||||
|
1. Запусти точную sprite-команду. Процесс должен завершиться с кодом `0` и сообщить имя, число иконок, mode и каталог `.svg-sprite`.
|
||||||
|
2. Проверь output выбранного exact mode:
|
||||||
|
- bare `standalone` создаёт `sprite.svg` и `svg-sprite.manifest.json`;
|
||||||
|
- `standalone@server` создаёт два content-addressed SVG profiles и server manifest, hashes и relative paths которого соответствуют этим файлам;
|
||||||
|
- `standalone@vite` и `standalone@webpack` дополнительно создают `index.*`, `icon-data.*` и JS manifest, но не каталог `react/`;
|
||||||
|
- framework modes также создают adapter-owned runtime нативного компонента, declaration и styles.
|
||||||
|
3. Для modes с public facade проверь `.svg-sprite/index.js`, соседний `index.d.ts`, список имён и фактический импорт через пользовательский barrel.
|
||||||
|
4. Проверь manifest: mode и target должны соответствовать выбранному adapter, а список иконок — исходным SVG. В bundler modes URL должен формироваться mode-specific способом; bare JSON manifest намеренно не содержит публичного `spriteUrl`.
|
||||||
|
5. Запусти существующий typecheck проекта, если mode создаёт типы или изменился пользовательский TypeScript-код.
|
||||||
|
6. Запусти минимальную команду приложения, затронутую изменением: `dev`, build или специализированную проверку проекта.
|
||||||
|
|
||||||
|
Не запускай полную production-сборку только ради проверки нового имени иконки. Она нужна, если менялся bundler target, router, Webpack loader, asset URL, deployment path или диагностируется production-only ошибка.
|
||||||
|
|
||||||
|
Визуальную проверку, Network и accessibility tree выполняй только при наличии запущенного приложения и браузерных инструментов. Если таких инструментов нет, не утверждай, что цвета, темы, доступность или HTTP-ответ asset проверены; явно укажи непроверенную часть.
|
||||||
|
|
||||||
|
Viewer используй для сложных цветов, transforms и массовой визуальной проверки. Не добавляй debug route ради обычной генерации одного спрайта.
|
||||||
|
|
||||||
|
## Диагностика
|
||||||
|
|
||||||
|
Сопоставь симптом с проверкой и исправляй первопричину:
|
||||||
|
|
||||||
|
| Симптом | Вероятная причина | Действие |
|
||||||
|
|---|---|---|
|
||||||
|
| `Missing sprite config file or module directory` | Не передан позиционный путь | Передай один config-файл либо каталог для config-less запуска. |
|
||||||
|
| `Expected one config file or module directory` | Передано несколько путей | Создай отдельную команду на каждый спрайт и объедини scripts. |
|
||||||
|
| `Sprite mode is required` | Mode отсутствует и в config, и в CLI | Добавь `mode` в объект или передай полный `--mode`. |
|
||||||
|
| `Unsupported sprite config extension` | Передан файл не `.ts`, `.js` или `.json` | Используй поддерживаемый формат config-файла. |
|
||||||
|
| Positive input-источник не нашёл SVG | Папка отсутствует или пуста, glob не совпал либо точный путь отсутствует или ведёт не к SVG | Разреши источник от каталога конфига и исправь `input`; каждый positive-элемент должен дать хотя бы один SVG. |
|
||||||
|
| Иконки из подпапки не появились | От папки ожидалось рекурсивное сканирование | Используй явный glob, например `./icons/**/*.svg`; папки сканируются плоско. |
|
||||||
|
| Исключённая иконка всё ещё присутствует | У исключения нет префикса `!`, оно находится не в массиве `input` или считается не от того каталога | Добавь совпадающий `!`-элемент и считай его от каталога конфига. |
|
||||||
|
| CLI выбрал не все источники | Несколько источников поместили в одно значение `--input` или пропустили option | Повтори `--input <path-or-glob>` отдельно для каждого источника или исключения. |
|
||||||
|
| Конфликт имени иконки или SVG ID | Два разных файла имеют одинаковый basename либо hash-ID столкнулся с именем | Переименуй один исходный SVG; не выбирай файл неявно. |
|
||||||
|
| `Refusing to overwrite a user file` | В корне sprite-модуля уже есть пользовательский `.gitignore`, который mode должен создать | Не перезаписывай файл: выбери другой sprite-каталог или согласуй перенос существующего `.gitignore`. |
|
||||||
|
| Нет `.svg-sprite/index.js` или имя отсутствует в autocomplete | Для bare `standalone` это ожидаемо; в остальных modes генерация не запускалась, barrel неверен либо type server держит старый модуль | Сверь exact mode, запусти sprite-команду, проверь `export * from './.svg-sprite/index.js'`, затем typecheck; при необходимости перезапусти TypeScript server. |
|
||||||
|
| SVG не загружается или URL неверен | Mode не совпадает со сборщиком, неверен Webpack `publicPath` либо кастомный loader перехватил asset | Сверь mode и build-команду, проверь Asset Modules/`publicPath`, исключи generated SVG из несовместимого loader. |
|
||||||
|
| Next build расходится между SSR и браузером | Модуль сгенерирован для другого bundler/router или URL переписан вручную | Верни generated `new URL(...)`, выбери точный Next mode и перегенерируй. |
|
||||||
|
| `color` не меняет многоцветную иконку | У иконки несколько переменных или она показана через `<img>`/CSS background | Используй `<FileManagerIcon>`/`<svg><use>` и нужные `--icon-color-N`. |
|
||||||
|
| Gradient/filter выглядит неверно | Автозамена цветов не гарантирует сложные paint servers | Изучи generated SVG; при необходимости отключи `replaceColors` для спрайта или упрости источник. |
|
||||||
|
| Viewer пуст | Manifest не создан, loader не обнаружен сборщиком или неверна Client Component boundary | Сначала сгенерируй спрайт, затем сверь manifest import и способ подключения с exact guide; в App Router оставь `'use client'` только в компоненте Viewer. |
|
||||||
|
| Remote manifest отклонён | Это не schema `standalone@server`, profile path небезопасен или metadata противоречивы | Опубликуй неизменённый полный server release и направь `input` на его JSON manifest. |
|
||||||
|
| Не прошла integrity-проверка remote sprite | SVG устарел, обрезан или изменён отдельно от manifest | Атомарно переопубликуй manifest и оба content-addressed profiles; никогда не перезаписывай hashed SVG другими байтами. |
|
||||||
|
|
||||||
|
При неизвестной ошибке зафиксируй полную CLI-команду, mode, путь к config-файлу или каталогу и первый stack/error message. Затем минимально воспроизведи проблему на одном спрайте, не удаляя пользовательские файлы и управляемый `.gitignore`.
|
||||||
|
|
||||||
|
## Карта reference-документации
|
||||||
|
|
||||||
|
References являются частью собранного skill. Открывай только документы, относящиеся к текущей задаче, но перед изменением интеграции exact-mode guide обязателен.
|
||||||
|
|
||||||
|
### Обзор
|
||||||
|
|
||||||
|
- [README пакета](./references/README_RU.md) — возможности, основной React/Next.js пример, все поддерживаемые families и ссылки на документацию.
|
||||||
|
|
||||||
|
### Конфигурация
|
||||||
|
|
||||||
|
- [Конфигурация](./references/docs/ru/configuration.md) — JSON, JavaScript, TypeScript, поля config, `input` и запуск CLI.
|
||||||
|
|
||||||
|
### Exact-mode guides
|
||||||
|
|
||||||
|
- [`standalone`](./references/docs/ru/guides/standalone.md) — static HTML и собственная публикация SVG.
|
||||||
|
- [`standalone@vite`](./references/docs/ru/guides/standalone-vite.md) — vanilla-приложение с Vite и Web Component.
|
||||||
|
- [`standalone@webpack`](./references/docs/ru/guides/standalone-webpack.md) — vanilla-приложение с Webpack 5 и Web Component.
|
||||||
|
- [`standalone@server`](./references/docs/ru/guides/standalone-server.md) — централизованный content-addressed release и remote consumers.
|
||||||
|
- [`react@vite`](./references/docs/ru/guides/react-vite.md) — React с Vite.
|
||||||
|
- [`react@webpack`](./references/docs/ru/guides/react-webpack.md) — React с Webpack 5.
|
||||||
|
- [`vue@vite`](./references/docs/ru/guides/vue-vite.md) — Vue с Vite.
|
||||||
|
- [`vue@webpack`](./references/docs/ru/guides/vue-webpack.md) — Vue с Webpack.
|
||||||
|
- [`nuxt@vite`](./references/docs/ru/guides/nuxt-vite.md) — Nuxt с Vite.
|
||||||
|
- [`nuxt@webpack`](./references/docs/ru/guides/nuxt-webpack.md) — Nuxt с Webpack.
|
||||||
|
- [`svelte@vite`](./references/docs/ru/guides/svelte-vite.md) — Svelte с Vite.
|
||||||
|
- [`svelte@webpack`](./references/docs/ru/guides/svelte-webpack.md) — Svelte с Webpack.
|
||||||
|
- [`sveltekit@vite`](./references/docs/ru/guides/sveltekit-vite.md) — SvelteKit с Vite.
|
||||||
|
- [`angular@application`](./references/docs/ru/guides/angular-application.md) — Angular application builder.
|
||||||
|
- [`angular@webpack`](./references/docs/ru/guides/angular-webpack.md) — Angular с Webpack.
|
||||||
|
- [`astro@vite`](./references/docs/ru/guides/astro-vite.md) — Astro с Vite.
|
||||||
|
- [`solid@vite`](./references/docs/ru/guides/solid-vite.md) — Solid с Vite.
|
||||||
|
- [`solid@webpack`](./references/docs/ru/guides/solid-webpack.md) — Solid с Webpack.
|
||||||
|
- [`solid-start@vite`](./references/docs/ru/guides/solid-start-vite.md) — SolidStart с Vite.
|
||||||
|
- [`preact@vite`](./references/docs/ru/guides/preact-vite.md) — Preact с Vite.
|
||||||
|
- [`preact@webpack`](./references/docs/ru/guides/preact-webpack.md) — Preact с Webpack.
|
||||||
|
- [`qwik@vite`](./references/docs/ru/guides/qwik-vite.md) — Qwik с Vite.
|
||||||
|
- [`lit@vite`](./references/docs/ru/guides/lit-vite.md) — Lit с Vite.
|
||||||
|
- [`lit@webpack`](./references/docs/ru/guides/lit-webpack.md) — Lit с Webpack.
|
||||||
|
- [`alpine@vite`](./references/docs/ru/guides/alpine-vite.md) — Alpine.js с Vite.
|
||||||
|
- [`alpine@webpack`](./references/docs/ru/guides/alpine-webpack.md) — Alpine.js с Webpack.
|
||||||
|
- [`next@app/turbopack`](./references/docs/ru/guides/next-app-turbopack.md) — Next.js App Router с Turbopack.
|
||||||
|
- [`next@app/webpack`](./references/docs/ru/guides/next-app-webpack.md) — Next.js App Router с Webpack.
|
||||||
|
- [`next@pages/turbopack`](./references/docs/ru/guides/next-pages-turbopack.md) — Next.js Pages Router с Turbopack.
|
||||||
|
- [`next@pages/webpack`](./references/docs/ru/guides/next-pages-webpack.md) — Next.js Pages Router с Webpack.
|
||||||
|
|
||||||
|
### Технические справочники
|
||||||
|
|
||||||
|
- [Технический справочник](./references/docs/ru/reference/technical.md) — requirements, CLI, naming, generated API, assets, transforms, цвета, Viewer, Git, CI и диагностика.
|
||||||
|
- [Программный API](./references/docs/ru/reference/programmatic-api.md) — `generateSprite`, overrides, config API, compiler и Viewer runtime.
|
||||||
|
|
||||||
|
### Agent-specific reference
|
||||||
|
|
||||||
|
- [Сложные SVG](./references/complex-svg.md) — gradients, patterns, filters, masks, `url(#...)`, `viewBox`, fragment IDs и визуальная диагностика.
|
||||||
303
skills/svg-sprites-ru/references/README_RU.md
Normal file
303
skills/svg-sprites-ru/references/README_RU.md
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
# @gromlab/svg-sprites
|
||||||
|
|
||||||
|
[🇬🇧 English](https://github.com/gromlab-ru/svg-sprites/blob/master/README.md) | 🇷🇺 Русский
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` — CLI-инструмент для генерации SVG-спрайтов в современных веб-приложениях. Он собирает выбранные SVG-иконки в один или несколько внешних кешируемых спрайтов и подготавливает их для использования в интерфейсе.
|
||||||
|
|
||||||
|
Каждый exact mode создаёт нативный типизированный компонент для своего framework и bundler: Web Component, React, Vue, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js. SVG во всех случаях остаётся отдельным кешируемым asset.
|
||||||
|
|
||||||
|
## SVG-спрайт так же прост, как обычная SVG-иконка
|
||||||
|
|
||||||
|
Для всего спрайта генерируется один типизированный React-компонент. Выберите иконку через `icon`, а редактор покажет автокомплит всех доступных имён.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" width={24} height={24} />
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент принимает привычные SVG-атрибуты: размеры, `color`, `className`, `style`, `aria-*` и обработчики событий. Если нужен внешний контейнер, добавьте `wrapped`.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||||
|
```
|
||||||
|
|
||||||
|
В приложении не приходится работать со спрайтом напрямую. Вы используете его так же, как обычную SVG-иконку, но получаете один компонент, автокомплит и TypeScript-проверку всех имён.
|
||||||
|
|
||||||
|
## AI-friendly из коробки
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` сразу рассчитан на работу с AI-агентами. Подключите готовый skill и поручите агенту настройку, миграцию или диагностику без длинных инструкций и ручного изучения документации.
|
||||||
|
|
||||||
|
Установить русскоязычный skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites-ru
|
||||||
|
```
|
||||||
|
|
||||||
|
Установить англоязычный skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
## От SVG до компонента за три шага
|
||||||
|
|
||||||
|
Основной пример использует Next.js App Router и Turbopack.
|
||||||
|
|
||||||
|
### 1. Укажите нужные иконки
|
||||||
|
|
||||||
|
Создайте папки для исходных иконок и спрайта:
|
||||||
|
|
||||||
|
```text
|
||||||
|
assets/
|
||||||
|
├── app-icons/
|
||||||
|
│ └── svg-sprite.config.json
|
||||||
|
└── svg-icons/
|
||||||
|
├── search.svg
|
||||||
|
└── settings.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте конфигурацию спрайта:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` поддерживает пути к папкам, отдельным SVG и glob-шаблоны.
|
||||||
|
|
||||||
|
### 2. Добавьте генерацию
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"prebuild": "npm run sprites"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте точку входа для сгенерированного API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// assets/app-icons/index.ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Первый запуск:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет создаст `AppIcon`, TypeScript-типы и отдельный SVG-спрайт.
|
||||||
|
|
||||||
|
### 3. Используйте как обычную иконку
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function SearchButton() {
|
||||||
|
return (
|
||||||
|
<button type="button">
|
||||||
|
<AppIcon icon="search" width={20} height={20} />
|
||||||
|
Найти
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Это Server Component. Для иконки не нужны provider, `'use client'` или ручная сборка URL.
|
||||||
|
|
||||||
|
## Типизированный React-компонент с автокомплитом
|
||||||
|
|
||||||
|
Каждый спрайт получает собственный готовый компонент. Свойство `icon` формируется из реальных имён SVG, поэтому редактор показывает точный список доступных иконок, а TypeScript сразу обнаруживает опечатки.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" /> // доступная иконка
|
||||||
|
<AppIcon icon="serach" /> // ошибка TypeScript
|
||||||
|
```
|
||||||
|
|
||||||
|
После добавления новой SVG-иконки и повторной генерации её имя автоматически появляется в типах и автокомплите. Не нужно вручную поддерживать компоненты, union-типы или реестр имён.
|
||||||
|
|
||||||
|
## Next.js App Router и SSR из коробки
|
||||||
|
|
||||||
|
Generated-компоненты работают в Server Components, SSR и SSG без `'use client'`.
|
||||||
|
|
||||||
|
Подключение иконки не переносит страницу на клиент, не требует provider и не создаёт дополнительную границу гидратации.
|
||||||
|
|
||||||
|
Один и тот же компонент можно использовать в `page.tsx`, `layout.tsx`, серверных и клиентских компонентах.
|
||||||
|
|
||||||
|
## Множественные спрайты вместо одного глобального
|
||||||
|
|
||||||
|
Проект не ограничен одним набором иконок. Создавайте независимые спрайты для общих элементов, отдельных страниц и крупных UI-модулей.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" />
|
||||||
|
<AnalyticsIcon icon="chart" />
|
||||||
|
<EditorIcon icon="bold" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Каждый набор получает собственный типизированный компонент и SVG asset, поэтому разделы приложения не несут иконки, которые им не нужны.
|
||||||
|
|
||||||
|
## Каждая иконка хранится в одном экземпляре
|
||||||
|
|
||||||
|
В библиотеке исходников каждая SVG-иконка хранится в одном экземпляре и может входить в любое количество спрайтов. Общие иконки не приходится копировать между страницами и модулями: они обновляются для всех наборов из одного места.
|
||||||
|
|
||||||
|
```text
|
||||||
|
search.svg ─┬─→ AppIcon
|
||||||
|
├─→ AnalyticsIcon
|
||||||
|
└─→ EditorIcon
|
||||||
|
```
|
||||||
|
|
||||||
|
Спрайты разделяются ради производительности, но библиотека исходных иконок остаётся единой.
|
||||||
|
|
||||||
|
## Браузерное кеширование
|
||||||
|
|
||||||
|
При стандартной конфигурации Vite, Webpack или Next.js каждый спрайт выпускается отдельным версионированным SVG-файлом.
|
||||||
|
|
||||||
|
Пока набор иконок не меняется, браузер может использовать сохранённую копию независимо от обновлений JavaScript приложения.
|
||||||
|
|
||||||
|
Изменение React-компонентов не требует повторно загружать геометрию всех иконок.
|
||||||
|
|
||||||
|
## JavaScript без SVG-балласта
|
||||||
|
|
||||||
|
Контуры иконок остаются во внешних SVG assets и не увеличивают chunks приложения.
|
||||||
|
|
||||||
|
```text
|
||||||
|
React-код → JavaScript chunks
|
||||||
|
SVG-иконки → отдельные SVG assets
|
||||||
|
```
|
||||||
|
|
||||||
|
JavaScript отвечает за интерфейс и поведение, а графика загружается и кешируется отдельно.
|
||||||
|
|
||||||
|
## Трансформации SVG из коробки
|
||||||
|
|
||||||
|
Во время генерации пакет автоматически подготавливает исходные SVG для интерфейса:
|
||||||
|
|
||||||
|
- удаляет фиксированные `width` и `height`;
|
||||||
|
- сохраняет существующий `viewBox`;
|
||||||
|
- преобразует `fill` и `stroke` в CSS-переменные;
|
||||||
|
- добавляет плавные transitions непосредственно в цветные элементы иконки.
|
||||||
|
|
||||||
|
Каждую трансформацию можно настроить или отключить независимо.
|
||||||
|
|
||||||
|
## Каждый цвет под контролем CSS
|
||||||
|
|
||||||
|
При генерации цвета `fill` и `stroke` автоматически преобразуются в CSS-переменные `--icon-color-N`.
|
||||||
|
|
||||||
|
Монохромная иконка наследует `currentColor`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" color="rebeccapurple" />
|
||||||
|
```
|
||||||
|
|
||||||
|
В многоцветной иконке каждый цвет можно менять отдельно:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="user"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#2563eb',
|
||||||
|
'--icon-color-2': '#dbeafe',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Темы, состояния и hover-эффекты создаются без редактирования SVG и дополнительных копий иконки.
|
||||||
|
|
||||||
|
## SpriteViewer: все спрайты на одной debug-странице
|
||||||
|
|
||||||
|
`SpriteViewer` рендерит спрайты всех поддерживаемых exact modes в одном месте. Один Web Component отвечает за визуал, а для React также доступен тонкий bridge к нему.
|
||||||
|
|
||||||
|
Для каждой иконки видны созданные CSS-переменные и их fallback-цвета. Значения можно менять прямо в Viewer и сразу наблюдать результат.
|
||||||
|
|
||||||
|
Здесь же доступны готовые примеры для framework из manifest, `<svg><use>`, `<img>` и CSS.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Viewer подключается только к внутренней debug-странице и не становится частью generated-компонентов иконок.
|
||||||
|
|
||||||
|
Bare standalone подключает Viewer через browser script и HTML element. Bundler и framework modes используют npm entry Web Component; React и Next.js также могут импортировать bridge из `@gromlab/svg-sprites/react`.
|
||||||
|
|
||||||
|
## 30 exact modes
|
||||||
|
|
||||||
|
Пакет поддерживает 30 изолированных exact modes: `standalone@server` для серверной генерации универсального SVG-спрайта и 29 consumer modes для современных frameworks и bundlers.
|
||||||
|
|
||||||
|
`standalone@server` позволяет заранее сгенерировать SVG-спрайт на сервере или в CI/CD и опубликовать его для совместного использования. Такой спрайт не привязан к конкретному framework или bundler и подходит всем consumer modes.
|
||||||
|
|
||||||
|
29 consumer modes охватывают standalone, React, Next.js, Vue, Nuxt, Svelte, SvelteKit, Angular, Astro, Solid, SolidStart, Preact, Qwik, Lit и Alpine.js в поддерживаемых вариантах Vite, Webpack, Turbopack и application builder.
|
||||||
|
|
||||||
|
Все 29 consumer modes могут работать как со спрайтами, сгенерированными локально в проекте, так и с универсальными спрайтами, заранее сгенерированными на сервере через `standalone@server`. API компонентов и способ использования иконок в приложении в обоих сценариях остаются одинаковыми.
|
||||||
|
|
||||||
|
Интеграционная матрица охватывает все 30 exact modes. Отдельный producer-стенд проверяет серверную генерацию универсального спрайта, а каждое из 29 consumer-приложений генерирует и рендерит два независимых спрайта: локальный и удалённый.
|
||||||
|
|
||||||
|
Все consumer-приложения проходят production build и Playwright-тесты, а типизированные modes дополнительно проверяются штатным toolchain фреймворка. Каждый E2E-тест подтверждает, что локальный и удалённый спрайты загружаются и отрисовываются, а также проверяет отсутствие browser errors и отображение обеих групп в SpriteViewer.
|
||||||
|
|
||||||
|
## Чистый Git
|
||||||
|
|
||||||
|
Bundler и framework modes создают локальный `.gitignore`, который исключает generated-файлы и не позволяет им засорять историю, pull requests и код проекта. Bare `standalone` оставляет политику репозитория приложению.
|
||||||
|
|
||||||
|
В bundler и framework modes в репозитории остаются исходные SVG, конфигурация и правило `.gitignore`, а локально и в CI спрайты, компоненты и типы заново создаются через `prebuild`.
|
||||||
|
|
||||||
|
## В production только иконки
|
||||||
|
|
||||||
|
Генерация полностью работает через `npx`, без добавления package в проект. Устанавливайте его как development dependency, только если нужны Viewer, типы конфига или программный API.
|
||||||
|
|
||||||
|
Production-компоненты используют только локальный generated-код, стили и внешний SVG-файл. Compiler и CLI не попадают в клиентское приложение, а `SpriteViewer` подключается отдельно только там, где нужна debug-страница.
|
||||||
|
|
||||||
|
## Документация
|
||||||
|
|
||||||
|
README знакомит с возможностями проекта и показывает основной сценарий использования. Для настройки выберите руководство под свой стек.
|
||||||
|
|
||||||
|
### Серверная генерация
|
||||||
|
|
||||||
|
- [Standalone + Server](docs/ru/guides/standalone-server.md)
|
||||||
|
|
||||||
|
### Быстрый старт для consumer modes
|
||||||
|
|
||||||
|
- [Bare standalone](docs/ru/guides/standalone.md)
|
||||||
|
- [Standalone + Vite](docs/ru/guides/standalone-vite.md)
|
||||||
|
- [Standalone + Webpack 5](docs/ru/guides/standalone-webpack.md)
|
||||||
|
- [React + Vite](docs/ru/guides/react-vite.md)
|
||||||
|
- [React + Webpack 5](docs/ru/guides/react-webpack.md)
|
||||||
|
- [Vue + Vite](docs/ru/guides/vue-vite.md)
|
||||||
|
- [Vue + Webpack](docs/ru/guides/vue-webpack.md)
|
||||||
|
- [Nuxt + Vite](docs/ru/guides/nuxt-vite.md)
|
||||||
|
- [Nuxt + Webpack](docs/ru/guides/nuxt-webpack.md)
|
||||||
|
- [Svelte + Vite](docs/ru/guides/svelte-vite.md)
|
||||||
|
- [Svelte + Webpack](docs/ru/guides/svelte-webpack.md)
|
||||||
|
- [SvelteKit + Vite](docs/ru/guides/sveltekit-vite.md)
|
||||||
|
- [Angular application builder](docs/ru/guides/angular-application.md)
|
||||||
|
- [Angular + Webpack](docs/ru/guides/angular-webpack.md)
|
||||||
|
- [Astro + Vite](docs/ru/guides/astro-vite.md)
|
||||||
|
- [Solid + Vite](docs/ru/guides/solid-vite.md)
|
||||||
|
- [Solid + Webpack](docs/ru/guides/solid-webpack.md)
|
||||||
|
- [SolidStart + Vite](docs/ru/guides/solid-start-vite.md)
|
||||||
|
- [Preact + Vite](docs/ru/guides/preact-vite.md)
|
||||||
|
- [Preact + Webpack](docs/ru/guides/preact-webpack.md)
|
||||||
|
- [Qwik + Vite](docs/ru/guides/qwik-vite.md)
|
||||||
|
- [Lit + Vite](docs/ru/guides/lit-vite.md)
|
||||||
|
- [Lit + Webpack](docs/ru/guides/lit-webpack.md)
|
||||||
|
- [Alpine.js + Vite](docs/ru/guides/alpine-vite.md)
|
||||||
|
- [Alpine.js + Webpack](docs/ru/guides/alpine-webpack.md)
|
||||||
|
- [Next.js App Router + Turbopack](docs/ru/guides/next-app-turbopack.md)
|
||||||
|
- [Next.js App Router + Webpack](docs/ru/guides/next-app-webpack.md)
|
||||||
|
- [Next.js Pages Router + Turbopack](docs/ru/guides/next-pages-turbopack.md)
|
||||||
|
- [Next.js Pages Router + Webpack](docs/ru/guides/next-pages-webpack.md)
|
||||||
|
|
||||||
|
### Технические материалы
|
||||||
|
|
||||||
|
- [Индекс документации](docs/ru/README.md)
|
||||||
|
- [Конфигурация](docs/ru/configuration.md)
|
||||||
|
- [Технический справочник](docs/ru/reference/technical.md)
|
||||||
|
- [Программный API](docs/ru/reference/programmatic-api.md)
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
MIT
|
||||||
56
skills/svg-sprites-ru/references/docs/ru/README.md
Normal file
56
skills/svg-sprites-ru/references/docs/ru/README.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Документация
|
||||||
|
|
||||||
|
Для настройки выберите guide одного exact mode. Каждый guide является
|
||||||
|
самостоятельным документом и без изменений используется в AI skills.
|
||||||
|
|
||||||
|
Общий формат JSON, JavaScript и TypeScript config-файлов описан в [руководстве по конфигурации](configuration.md).
|
||||||
|
|
||||||
|
## Быстрый старт для consumer modes
|
||||||
|
|
||||||
|
| Проект | Exact mode | Guide |
|
||||||
|
|---|---|---|
|
||||||
|
| Static HTML или собственная публикация | `standalone` | [Bare standalone](guides/standalone.md) |
|
||||||
|
| Vanilla + Vite | `standalone@vite` | [Standalone + Vite](guides/standalone-vite.md) |
|
||||||
|
| Vanilla + Webpack 5 | `standalone@webpack` | [Standalone + Webpack](guides/standalone-webpack.md) |
|
||||||
|
| React + Vite | `react@vite` | [React + Vite](guides/react-vite.md) |
|
||||||
|
| React + Webpack 5 | `react@webpack` | [React + Webpack](guides/react-webpack.md) |
|
||||||
|
| Vue + Vite | `vue@vite` | [Vue + Vite](guides/vue-vite.md) |
|
||||||
|
| Vue + Webpack | `vue@webpack` | [Vue + Webpack](guides/vue-webpack.md) |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` | [Nuxt + Vite](guides/nuxt-vite.md) |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` | [Nuxt + Webpack](guides/nuxt-webpack.md) |
|
||||||
|
| Svelte + Vite | `svelte@vite` | [Svelte + Vite](guides/svelte-vite.md) |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` | [Svelte + Webpack](guides/svelte-webpack.md) |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` | [SvelteKit + Vite](guides/sveltekit-vite.md) |
|
||||||
|
| Angular application builder | `angular@application` | [Angular application builder](guides/angular-application.md) |
|
||||||
|
| Angular + Webpack | `angular@webpack` | [Angular + Webpack](guides/angular-webpack.md) |
|
||||||
|
| Astro + Vite | `astro@vite` | [Astro + Vite](guides/astro-vite.md) |
|
||||||
|
| Solid + Vite | `solid@vite` | [Solid + Vite](guides/solid-vite.md) |
|
||||||
|
| Solid + Webpack | `solid@webpack` | [Solid + Webpack](guides/solid-webpack.md) |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` | [SolidStart + Vite](guides/solid-start-vite.md) |
|
||||||
|
| Preact + Vite | `preact@vite` | [Preact + Vite](guides/preact-vite.md) |
|
||||||
|
| Preact + Webpack | `preact@webpack` | [Preact + Webpack](guides/preact-webpack.md) |
|
||||||
|
| Qwik + Vite | `qwik@vite` | [Qwik + Vite](guides/qwik-vite.md) |
|
||||||
|
| Lit + Vite | `lit@vite` | [Lit + Vite](guides/lit-vite.md) |
|
||||||
|
| Lit + Webpack | `lit@webpack` | [Lit + Webpack](guides/lit-webpack.md) |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` | [Alpine.js + Vite](guides/alpine-vite.md) |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` | [Alpine.js + Webpack](guides/alpine-webpack.md) |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` | [App Router + Turbopack](guides/next-app-turbopack.md) |
|
||||||
|
| Next.js App Router + Webpack | `next@app/webpack` | [App Router + Webpack](guides/next-app-webpack.md) |
|
||||||
|
| Next.js Pages Router + Turbopack | `next@pages/turbopack` | [Pages Router + Turbopack](guides/next-pages-turbopack.md) |
|
||||||
|
| Next.js Pages Router + Webpack | `next@pages/webpack` | [Pages Router + Webpack](guides/next-pages-webpack.md) |
|
||||||
|
|
||||||
|
Все consumer guides используют один порядок:
|
||||||
|
|
||||||
|
1. Генерация спрайта через `npx` без добавления package в проект.
|
||||||
|
2. Использование спрайта в приложении.
|
||||||
|
3. Необязательное подключение Viewer для дебага и превью.
|
||||||
|
|
||||||
|
## Серверная генерация
|
||||||
|
|
||||||
|
Используйте [`standalone@server`](guides/standalone-server.md), чтобы сгенерировать на сервере или в CI/CD универсальный SVG-спрайт для всех consumer modes.
|
||||||
|
|
||||||
|
## Справочники
|
||||||
|
|
||||||
|
- [Конфигурация](configuration.md)
|
||||||
|
- [Технический справочник](reference/technical.md)
|
||||||
|
- [Программный API](reference/programmatic-api.md)
|
||||||
139
skills/svg-sprites-ru/references/docs/ru/configuration.md
Normal file
139
skills/svg-sprites-ru/references/docs/ru/configuration.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# Конфигурация
|
||||||
|
|
||||||
|
Каждый 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 и сборщику |
|
||||||
|
| `source` | `local` | `local` для исходных SVG или `remote` для manifest от `standalone@server` |
|
||||||
|
| `name` | Kebab-case имени каталога модуля; для `svg-sprite` и `svg-sprites` — имени родительского каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и типов |
|
||||||
|
| `description` | Нет | Описание для типов и Viewer |
|
||||||
|
| `input` | `./icons` | Каталог, SVG-файл, glob-шаблон или массив источников |
|
||||||
|
| `transform` | Все включены | Настройки подготовки SVG |
|
||||||
|
| `generatedNotice` | `true` | Вид предупреждения в generated-файлах |
|
||||||
|
|
||||||
|
Пути и glob-шаблоны в `input` считаются от каталога config-файла. Паттерн с префиксом `!` исключает совпадения.
|
||||||
|
|
||||||
|
## Удалённо собранный спрайт
|
||||||
|
|
||||||
|
Consumer config для server manifest содержит только mode, source и input:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"source": "remote",
|
||||||
|
"input": "https://assets.example/releases/app/svg-sprite.manifest.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` принимает один HTTP(S) URL или локальный путь к manifest. Имя, описание,
|
||||||
|
transforms и generated notice берутся из manifest. Генератор скачивает и проверяет
|
||||||
|
подходящий SVG profile, после чего adapter создаёт обычные локальные компоненты,
|
||||||
|
типы и asset для сборщика.
|
||||||
|
|
||||||
|
## Серверная сборка
|
||||||
|
|
||||||
|
`standalone@server` объединяет local paths/globs и HTTP(S) SVG descriptors:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
mode: 'standalone@server',
|
||||||
|
name: 'app',
|
||||||
|
input: [
|
||||||
|
'./icons/**/*.svg',
|
||||||
|
{
|
||||||
|
name: 'remote-logo',
|
||||||
|
url: 'https://assets.example/logo.svg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Mode создаёт два content-addressed SVG profiles и `svg-sprite.manifest.json`.
|
||||||
|
`sha256` у HTTP input необязателен; если он указан, это должен быть ожидаемый
|
||||||
|
64-символьный hexadecimal SHA-256 digest, по которому сборка проверит полученные байты.
|
||||||
|
|
||||||
|
## 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).
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# SVG-спрайт для Alpine.js на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Alpine.js-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "alpine@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Генератор не нужно добавлять в зависимости приложения: запускайте его через `npx`.
|
||||||
|
|
||||||
|
Добавьте генерацию перед запуском разработки и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Alpine plugin `appAlpinePlugin`, директиву `x-app-icon` и magic `$appIconHref`.
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте generated plugin до запуска Alpine:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
import { appAlpinePlugin } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
Alpine.plugin(appAlpinePlugin)
|
||||||
|
Alpine.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте реактивную директиву на SVG-элементе:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
x-data="{ iconName: 'icon-name' }"
|
||||||
|
x-app-icon="iconName"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Выражение директивы возвращает имя исходного SVG без расширения. Монохромная иконка наследует `color`, а слои многоцветной иконки переопределяются через `--icon-color-N`. Vite подключает generated CSS и выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице и нужен только при разработке. Установите его отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer на development-страницу:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<gromlab-sprite-viewer viewer-title="Иконки проекта"></gromlab-sprite-viewer>
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `src/svg-sprite-debug.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте development-страницу. Viewer не зависит от Alpine plugin.
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# SVG-спрайт для Alpine.js на Webpack 5
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Alpine.js-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "alpine@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Генератор не нужно добавлять в зависимости приложения: запускайте его через `npx`.
|
||||||
|
|
||||||
|
Добавьте генерацию перед запуском разработки и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Alpine plugin `appAlpinePlugin`, директиву `x-app-icon` и magic `$appIconHref`.
|
||||||
|
|
||||||
|
Generated CSS Alpine импортируется с query `?inline`. Добавьте правило Asset Modules в `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
resourceQuery: /inline/,
|
||||||
|
type: 'asset/source',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте generated plugin до запуска Alpine:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
import { appAlpinePlugin } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
Alpine.plugin(appAlpinePlugin)
|
||||||
|
Alpine.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте реактивную директиву на SVG-элементе:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
x-data="{ iconName: 'icon-name' }"
|
||||||
|
x-app-icon="iconName"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Выражение директивы возвращает имя исходного SVG без расширения. Монохромная иконка наследует `color`, а слои многоцветной иконки переопределяются через `--icon-color-N`. Webpack 5 выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице и нужен только при разработке. Установите его отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer в development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.viewerTitle = 'Иконки проекта'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключайте этот entry только при разработке. Viewer не зависит от Alpine plugin.
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# SVG-спрайт для Angular с Application Builder
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Angular-приложении на `@angular/build:application`.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "angular@application",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Запускайте генерацию через `npx` перед разработкой и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"prestart": "npm run sprites",
|
||||||
|
"start": "ng serve",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "ng build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Application Builder выпускает импортированный SVG отдельным файлом при включённом file loader. Добавьте опцию в build target файла `angular.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"builder": "@angular/build:application",
|
||||||
|
"options": {
|
||||||
|
"loader": { ".svg": "file" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index'
|
||||||
|
```
|
||||||
|
|
||||||
|
Импортируйте сгенерированный standalone-компонент. Значение `name: "app"` создаёт `AppIcon` с селектором `app-icon`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [AppIcon],
|
||||||
|
template: `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width: 24px; height: 24px; color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class AppComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Input `icon` типизирован именами исходных файлов. Монохромные иконки наследуют `color`, отдельные цвета задаются через `--icon-color-N`.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer необязателен и нужен только при разработке:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Импортируйте `@gromlab/svg-sprites/viewer/element`, добавьте `CUSTOM_ELEMENTS_SCHEMA` и поместите `<gromlab-sprite-viewer [sources]="viewerSources" />` в шаблон. Загрузите generated manifest без framework-specific metadata:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
readonly viewerSources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
Viewer использует тот же production URL спрайта, что и `AppIcon`.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# SVG-спрайт для Angular на Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Angular-приложении со штатным Webpack browser builder из Angular CLI.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "angular@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Mode предназначен для workspace, где build target использует официальный Webpack builder:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"builder": "@angular-devkit/build-angular:browser"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Генерируйте спрайт через `npx` перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"prestart": "npm run sprites",
|
||||||
|
"start": "ng serve",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "ng build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack разрешает generated-выражение `new URL(..., import.meta.url)` и выпускает `sprite.svg` как production asset.
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index'
|
||||||
|
```
|
||||||
|
|
||||||
|
Импортируйте сгенерированный standalone-компонент. Значение `name: "app"` создаёт `AppIcon` с селектором `app-icon`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [AppIcon],
|
||||||
|
template: `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width: 24px; height: 24px; color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class AppComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Input `icon` типизирован именами исходных файлов. Монохромные иконки наследуют `color`, отдельные цвета задаются через `--icon-color-N`.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer необязателен и нужен только при разработке:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Импортируйте `@gromlab/svg-sprites/viewer/element`, добавьте `CUSTOM_ELEMENTS_SCHEMA` и поместите `<gromlab-sprite-viewer [sources]="viewerSources" />` в шаблон:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
readonly viewerSources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
Viewer и `AppIcon` используют один выпущенный Webpack URL спрайта.
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# SVG-спрайт для Astro на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Astro-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "astro@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Генерируйте спрайт через `npx` перед разработкой и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "astro dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "astro check && astro build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.d.ts` для того же типизированного API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт нативный Astro-компонент `AppIcon`. Используйте его на странице:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
---
|
||||||
|
import { AppIcon } from '../../assets/app-icons/index.js'
|
||||||
|
---
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Prop `icon` типизирован именами исходных файлов. Vite выпускает `sprite.svg` из статического asset import компонента.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer необязателен и нужен только при разработке:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer на страницу и подключите generated manifest в клиентском скрипте:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
<gromlab-sprite-viewer id="sprite-viewer"></gromlab-sprite-viewer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('#sprite-viewer')!
|
||||||
|
viewer.sources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Manifest сохраняет Astro usage metadata, а Viewer отображает тот же production-спрайт.
|
||||||
86
skills/svg-sprites-ru/references/docs/ru/guides/lit-vite.md
Normal file
86
skills/svg-sprites-ru/references/docs/ru/guides/lit-vite.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# SVG-спрайт для Lit на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Lit-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "lit@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Генератор не нужно добавлять в зависимости приложения: запускайте его через `npx`.
|
||||||
|
|
||||||
|
Добавьте генерацию перед запуском разработки и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Lit-класс `AppIcon`, тег `<app-icon>` и функцию регистрации `defineAppIcon`.
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте компонент перед его отображением:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineAppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
defineAppIcon()
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></app-icon>
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имя исходного SVG без расширения. Монохромная иконка наследует `color`, а слои многоцветной иконки переопределяются через `--icon-color-N`. Vite подключает CSS компонента и выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице и нужен только при разработке. Установите его отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer на development-страницу:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<gromlab-sprite-viewer viewer-title="Иконки проекта"></gromlab-sprite-viewer>
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `src/svg-sprite-debug.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте development-страницу. Viewer не требуется для работы `AppIcon`.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG-спрайт для Lit на Webpack 5
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Lit-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "lit@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Генератор не нужно добавлять в зависимости приложения: запускайте его через `npx`.
|
||||||
|
|
||||||
|
Добавьте генерацию перед запуском разработки и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Lit-класс `AppIcon`, тег `<app-icon>` и функцию регистрации `defineAppIcon`.
|
||||||
|
|
||||||
|
Generated CSS Lit импортируется с query `?inline`. Добавьте правило Asset Modules в `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
resourceQuery: /inline/,
|
||||||
|
type: 'asset/source',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте компонент перед его отображением:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineAppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
defineAppIcon()
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></app-icon>
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имя исходного SVG без расширения. Монохромная иконка наследует `color`, а слои многоцветной иконки переопределяются через `--icon-color-N`. Webpack 5 выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице и нужен только при разработке. Установите его отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer в development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.viewerTitle = 'Иконки проекта'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключайте этот entry только при разработке. Viewer не требуется для работы `AppIcon`.
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# SVG-спрайт для Next.js App Router с Turbopack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с App Router и Turbopack.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в Server Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Для `AppIcon` не нужен `'use client'`. Turbopack сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function SvgSpriteViewer() {
|
||||||
|
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте маршрут `app/svg-sprite/page.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
|
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
if (process.env.NODE_ENV !== 'development') notFound()
|
||||||
|
|
||||||
|
return <SvgSpriteViewer />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# SVG-спрайт для Next.js App Router с Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с App Router и Webpack.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в Server Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Для `AppIcon` не нужен `'use client'`. Next.js сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function SvgSpriteViewer() {
|
||||||
|
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте маршрут `app/svg-sprite/page.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
|
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
if (process.env.NODE_ENV !== 'development') notFound()
|
||||||
|
|
||||||
|
return <SvgSpriteViewer />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG-спрайт для Next.js Pages Router с Turbopack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с Pages Router и Turbopack.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@pages/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент на странице:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// pages/index.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент работает с SSR, SSG и клиентскими переходами. Turbopack сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте страницу `pages/svg-sprite.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import type { GetStaticProps } from 'next'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = () =>
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
? { props: {} }
|
||||||
|
: { notFound: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG-спрайт для Next.js Pages Router с Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении Next.js с Pages Router и Webpack.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@pages/webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент на странице:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// pages/index.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент работает с SSR, SSG и клиентскими переходами. Next.js сам добавляет `sprite.svg` в итоговую сборку, поэтому переносить его в `public` не нужно.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте страницу `pages/svg-sprite.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import type { GetStaticProps } from 'next'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
return <SpriteViewer sources={sources} title="Иконки проекта" />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = () =>
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
? { props: {} }
|
||||||
|
: { notFound: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite`. В production маршрут вернёт 404.
|
||||||
100
skills/svg-sprites-ru/references/docs/ru/guides/nuxt-vite.md
Normal file
100
skills/svg-sprites-ru/references/docs/ru/guides/nuxt-vite.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# SVG-спрайт для Nuxt на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Nuxt-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "nuxt@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "nuxt build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Vue-компонент `AppIcon`. Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент на странице или в layout Nuxt:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` безопасен для SSR и не требует client-only обёртки. Vite выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `app/components/SvgSpriteViewer.client.vue`, чтобы browser-only Viewer не выполнялся во время SSR:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer :sources="sources" viewer-title="Иконки проекта" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Отметьте `gromlab-sprite-viewer` как custom element в `nuxt.config.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
vue: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Покажите `<SvgSpriteViewer />` на странице разработки. Viewer изолирован от generated runtime компонента `AppIcon`.
|
||||||
113
skills/svg-sprites-ru/references/docs/ru/guides/nuxt-webpack.md
Normal file
113
skills/svg-sprites-ru/references/docs/ru/guides/nuxt-webpack.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# SVG-спрайт для Nuxt на Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Nuxt-приложении на Webpack.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "nuxt@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Подключите Webpack builder Nuxt в `nuxt.config.ts`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @nuxt/webpack-builder
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
builder: '@nuxt/webpack-builder',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "nuxt build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Vue-компонент `AppIcon`. Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент на странице или в layout Nuxt:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` безопасен для SSR и не требует client-only обёртки. Webpack выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `app/components/SvgSpriteViewer.client.vue`, чтобы browser-only Viewer не выполнялся во время SSR:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer :sources="sources" viewer-title="Иконки проекта" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Дополните существующие настройки `nuxt.config.ts`, чтобы Vue считал Viewer custom element:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
builder: '@nuxt/webpack-builder',
|
||||||
|
vue: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Покажите `<SvgSpriteViewer />` на странице разработки. Viewer изолирован от generated runtime компонента `AppIcon`.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG-спрайт для Preact на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Preact-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "preact@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Запускайте его через `npx` перед разработкой и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js` и `assets/app-icons/index.d.ts` с одинаковым экспортом:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте сгенерированный Preact-компонент на plain JavaScript:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Vite автоматически выпускает импортированный `sprite.svg` как production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Установите Viewer только для разработки:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключите его в отладочной entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG-спрайт для Preact на Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Preact-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "preact@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Запускайте его через `npx` перед запуском и сборкой Webpack:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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": "tsc --noEmit && webpack --mode production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js` и `assets/app-icons/index.d.ts` с одинаковым экспортом:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте сгенерированный Preact-компонент:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack Asset Modules выпускают `sprite.svg` из сгенерированного выражения `new URL(...)`.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Установите Viewer только для разработки:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключите его в отдельной development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
82
skills/svg-sprites-ru/references/docs/ru/guides/qwik-vite.md
Normal file
82
skills/svg-sprites-ru/references/docs/ru/guides/qwik-vite.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# SVG-спрайт для Qwik на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в SSR-приложении Qwik на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "qwik@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Перегенерируйте спрайт через `npx` перед запуском и сборкой Vite:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite --mode ssr",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "tsc --noEmit && vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Сгенерированный компонент является Qwik `component$` и безопасен во время SSR:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { component$ } from '@builder.io/qwik'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default component$(() => (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент использует статический Vite asset import и не обращается к browser globals во время SSR.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer работает только в браузере и нужен лишь для разработки:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Загрузите его из visible task:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export const IconViewer = component$(() => {
|
||||||
|
const host = useSignal<HTMLElement>()
|
||||||
|
useVisibleTask$(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.value?.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
})
|
||||||
|
```
|
||||||
115
skills/svg-sprites-ru/references/docs/ru/guides/react-vite.md
Normal file
115
skills/svg-sprites-ru/references/docs/ru/guides/react-vite.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# SVG-спрайт для React на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в React-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite сам подключает стили компонента и добавляет `sprite.svg` в итоговую сборку.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `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('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
createRoot(document.getElementById('svg-sprite-viewer')!).render(
|
||||||
|
<SpriteViewer sources={sources} title="Иконки проекта" />,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite.html`.
|
||||||
|
|
||||||
|
Стандартная production-сборка Vite использует только `index.html` и не включает страницу Viewer.
|
||||||
132
skills/svg-sprites-ru/references/docs/ru/guides/react-webpack.md
Normal file
132
skills/svg-sprites-ru/references/docs/ru/guides/react-webpack.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# SVG-спрайт для React на Webpack 5
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в React-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт React-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||||
|
|
||||||
|
Компонент использует CSS Modules. Если проект ещё не обрабатывает их, установите loaders:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev style-loader css-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
Затем добавьте правило с default export в `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.module\.css$/i,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: { modules: { namedExport: false } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 сам добавляет `sprite.svg` в итоговую сборку.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки.
|
||||||
|
|
||||||
|
Установите Viewer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте entry `src/svg-sprite-debug.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const container = document.createElement('div')
|
||||||
|
document.body.append(container)
|
||||||
|
|
||||||
|
createRoot(container).render(
|
||||||
|
<SpriteViewer sources={sources} title="Иконки проекта" />,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте скрипт к основному entry только в development-режиме. Сохраните остальные настройки `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default (_env, argv) => ({
|
||||||
|
// Остальные настройки Webpack.
|
||||||
|
entry: [
|
||||||
|
'./src/main.tsx',
|
||||||
|
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.tsx'] : []),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev`. Viewer появится на основной странице приложения и не попадёт в production-сборку.
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG-спрайт для SolidStart на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в SSR-приложении SolidStart на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid-start@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Перегенерируйте спрайт через `npx` перед запуском и сборкой Vinxi:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vinxi dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vinxi build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Сгенерированный компонент безопасно рендерится на сервере:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент использует статический Vite asset import и не обращается к browser globals во время SSR.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer работает только в браузере и нужен лишь для разработки:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Загрузите его из `onMount`, чтобы исключить из серверного рендера:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { onMount } from 'solid-js'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export function IconViewer() {
|
||||||
|
let host!: HTMLDivElement
|
||||||
|
onMount(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG-спрайт для Solid на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Solid-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Запускайте его через `npx` перед разработкой и production-сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Имя `app` создаёт Solid-компонент `AppIcon`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Vite выпускает `sprite.svg` как production asset. Монохромные иконки наследуют `color`, многоцветные используют `--icon-color-N`.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer нужен только во время разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключите его в отладочном компоненте после запуска браузерного кода:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { onMount } from 'solid-js'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export function IconViewer() {
|
||||||
|
let host!: HTMLDivElement
|
||||||
|
onMount(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG-спрайт для Solid на Webpack
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Solid-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта. Запускайте его через `npx` перед запуском и сборкой Webpack:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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": "tsc --noEmit && webpack --mode production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js` и `assets/app-icons/index.d.ts` с одинаковым экспортом:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте сгенерированный Solid-компонент:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Готово"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack Asset Modules выпускают `sprite.svg` из сгенерированного `new URL(...)`. Обработка `.jsx` должна охватывать сгенерированный Solid-компонент.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Установите Viewer только для разработки:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключите его в отдельной development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Универсальный SVG-спрайт на сервере
|
||||||
|
|
||||||
|
Сгенерируйте в CI или server worker универсальный SVG-спрайт, который смогут использовать приложения с разными frameworks и bundlers.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Устанавливать пакет в worker не нужно.
|
||||||
|
|
||||||
|
### 1. Подготовьте рабочий каталог
|
||||||
|
|
||||||
|
Поместите исходные SVG в папку `icons` текущего workspace:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
└── icons/
|
||||||
|
├── search.svg
|
||||||
|
└── settings.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
Имена файлов без расширения станут именами иконок.
|
||||||
|
|
||||||
|
### 2. Запустите генерацию
|
||||||
|
|
||||||
|
Передайте mode, имя спрайта и путь к SVG через CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites \
|
||||||
|
--mode standalone@server \
|
||||||
|
--name app \
|
||||||
|
--input './icons/**/*.svg' \
|
||||||
|
.
|
||||||
|
```
|
||||||
|
|
||||||
|
Config-файл для этого worker-сценария не нужен. Результат появится в `./.svg-sprite`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── icons/
|
||||||
|
│ ├── search.svg
|
||||||
|
│ └── settings.svg
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Опубликуйте результат
|
||||||
|
|
||||||
|
Загрузите содержимое `.svg-sprite` в отдельный каталог S3 bucket:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
aws s3 sync ./.svg-sprite/ s3://my-bucket/app-icons/
|
||||||
|
```
|
||||||
|
|
||||||
|
Этот же каталог можно раздавать через CDN. В публичном URL нет сегмента `.svg-sprite`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://cdn.example.com/app-icons/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`standalone@server` также можно запускать через JSON, JavaScript или TypeScript config. Config подходит для постоянных настроек, локальных SVG из нескольких каталогов и SVG, загружаемых по HTTP(S).
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
В consumer-приложении создайте обычный config. Например, для React с Vite:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/app-icons/
|
||||||
|
├── index.ts
|
||||||
|
└── svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Укажите consumer mode и URL manifest из CDN:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"source": "remote",
|
||||||
|
"input": "https://cdn.example.com/app-icons/svg-sprite.manifest.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте пользовательскую точку входа:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/app-icons/index.ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите обычную генерацию:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites src/app-icons/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
После этого используйте generated-компонент так же, как со спрайтом из локальных SVG:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from './app-icons'
|
||||||
|
|
||||||
|
export function SearchButton() {
|
||||||
|
return <AppIcon icon="search" aria-label="Поиск" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Тот же CDN manifest поддерживают все 29 consumer modes. В каждом из них сохраняется нативный API выбранного framework и bundler.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
`standalone@server` не создаёт отдельную страницу для просмотра иконок. Подключите опубликованный спрайт к consumer-приложению и откройте его в SpriteViewer: удалённый набор будет отображаться так же, как локальный.
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# SVG-спрайт для Vite без фреймворка
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении на Vite без фреймворка.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт элемент `<app-icon>`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте элемент в `src/main.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '../assets/app-icons'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте иконку в HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="icon-name" role="img" aria-label="Готово"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
Значение `icon` — имя исходного SVG без расширения. Размер и цвета настраиваются через CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
app-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #334155;
|
||||||
|
--icon-color-2: #f59e0b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Монохромная иконка наследует `color`, а цвета многоцветной иконки переопределяются через `--icon-color-N`. Нужные переменные показывает Viewer.
|
||||||
|
|
||||||
|
Vite сам добавит `sprite.svg` в итоговую сборку. Копировать его в `public` не нужно.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `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 '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite.html`.
|
||||||
|
|
||||||
|
Viewer не требуется для работы `<app-icon>` и не подключается к основному коду приложения.
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# SVG-спрайт для Webpack 5 без фреймворка
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в приложении на Webpack 5 без фреймворка.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт элемент `<app-icon>`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Зарегистрируйте элемент в основном entry приложения:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '../assets/app-icons'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте иконку в HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="icon-name" role="img" aria-label="Готово"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
Значение `icon` — имя исходного SVG без расширения. Размер и цвета настраиваются через CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
app-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #334155;
|
||||||
|
--icon-color-2: #f59e0b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Монохромная иконка наследует `color`, а цвета многоцветной иконки переопределяются через `--icon-color-N`. Нужные переменные показывает Viewer.
|
||||||
|
|
||||||
|
Webpack 5 сам добавит `sprite.svg` в итоговую сборку.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки.
|
||||||
|
|
||||||
|
Установите Viewer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте entry `src/svg-sprite-debug.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.viewerTitle = 'Иконки проекта'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте скрипт к основному entry только в development-режиме. Сохраните остальные настройки `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default (_env, argv) => ({
|
||||||
|
// Остальные настройки Webpack.
|
||||||
|
entry: [
|
||||||
|
'./src/main.ts',
|
||||||
|
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.ts'] : []),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev`. Viewer появится на основной странице приложения.
|
||||||
|
|
||||||
|
Viewer добавляется только в development-сборку и не попадает в production.
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG-спрайт для сайта без сборщика
|
||||||
|
|
||||||
|
Соберите SVG-иконки в один файл и используйте их на HTML-странице.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Устанавливать пакет в проект не нужно.
|
||||||
|
|
||||||
|
### 1. Создайте конфиг спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone",
|
||||||
|
"name": "icons",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Сгенерируйте спрайт
|
||||||
|
|
||||||
|
Передайте команде путь к конфигу:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет соберёт иконки в каталог `.svg-sprite` рядом с конфигом:
|
||||||
|
|
||||||
|
```text
|
||||||
|
assets/app-icons/.svg-sprite/
|
||||||
|
├── sprite.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
- `sprite.svg` — готовый спрайт для использования на сайте.
|
||||||
|
- `svg-sprite.manifest.json` — данные об иконках для Viewer.
|
||||||
|
|
||||||
|
Каталог `.svg-sprite` создаётся автоматически и полностью заменяется при каждой генерации. Не редактируйте его содержимое вручную.
|
||||||
|
|
||||||
|
### 3. Используйте иконку
|
||||||
|
|
||||||
|
В `index.html` укажите путь к созданному `sprite.svg`. После `#` добавьте имя нужной иконки без расширения `.svg`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
aria-label="Готово"
|
||||||
|
>
|
||||||
|
<use href="./assets/app-icons/.svg-sprite/sprite.svg#icon-name"></use>
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
`sprite.svg` — технический файл, а не галерея иконок. При его открытии нельзя удобно просмотреть весь набор. Кроме того, градиенты, маски, фильтры и ссылки на внутренние `id` могут отображаться с артефактами.
|
||||||
|
|
||||||
|
Для визуальной проверки используйте официальный Viewer. Он показывает все иконки спрайта и помогает проверить их цвета и отображение.
|
||||||
|
|
||||||
|
Viewer необязателен и предназначен только для разработки. Устанавливать пакет через npm не нужно.
|
||||||
|
|
||||||
|
Viewer работает напрямую с файлами из `.svg-sprite`. Ничего копировать не нужно.
|
||||||
|
|
||||||
|
### Добавьте Viewer на страницу
|
||||||
|
|
||||||
|
Добавьте в `index.html` module script и укажите пути к generated manifest и спрайту:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="https://cdn.jsdelivr.net/npm/@gromlab/svg-sprites/dist/viewer-element.js"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
viewer-title="Иконки проекта"
|
||||||
|
manifest-url="./assets/app-icons/.svg-sprite/svg-sprite.manifest.json"
|
||||||
|
sprite-url="./assets/app-icons/.svg-sprite/sprite.svg"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Viewer можно вынести в отдельный HTML-файл в корне сайта, предназначенный только для разработки и проверки иконок.
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# SVG-спрайт для Svelte на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Svelte-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "svelte@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Svelte-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite сам подключает стили компонента и выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer на страницу или в компонент, используемый только при разработке:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
node.sources = sources
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
use:connectViewer
|
||||||
|
viewer-title="Иконки проекта"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте страницу с Viewer. Не импортируйте этот отладочный компонент из production entry.
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# SVG-спрайт для Svelte на Webpack 5
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Svelte-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "svelte@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Svelte-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Generated-компонент является нативным `.svelte`-файлом. Обычное правило `svelte-loader` должно обрабатывать `.svelte`-файлы в `assets`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.svelte$/,
|
||||||
|
use: {
|
||||||
|
loader: 'svelte-loader',
|
||||||
|
options: { emitCss: false },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 обрабатывает asset URL из компонента и выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer в Svelte-компонент, используемый только при разработке:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
node.sources = sources
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
use:connectViewer
|
||||||
|
viewer-title="Иконки проекта"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте страницу с Viewer. Не импортируйте этот отладочный компонент из production entry.
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# SVG-спрайт для SvelteKit на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в SvelteKit-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "sveltekit@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт SSR-safe Svelte-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в `src/routes/+page.svelte`:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. В компоненте нет browser-only инициализации, поэтому страница может рендериться на сервере. Vite выпускает `sprite.svg` отдельным production asset.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте отладочный route, например `src/routes/svg-sprite/+page.svelte`. Загружайте custom element из action, чтобы регистрация выполнялась только в браузере:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
const sources = [
|
||||||
|
() => import('../../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
void import('@gromlab/svg-sprites/viewer/element').then(() => {
|
||||||
|
node.sources = sources
|
||||||
|
node.viewerTitle = 'Иконки проекта'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer use:connectViewer></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite`. Action не выполняется во время SSR.
|
||||||
105
skills/svg-sprites-ru/references/docs/ru/guides/vue-vite.md
Normal file
105
skills/svg-sprites-ru/references/docs/ru/guides/vue-vite.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# SVG-спрайт для Vue на Vite
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Vue-приложении на Vite.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "vue@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vue-tsc --noEmit && vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Vue-компонент `AppIcon`.
|
||||||
|
|
||||||
|
Создайте точку входа `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite сам подключает стили компонента и добавляет `sprite.svg` в итоговую сборку.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Создайте `svg-sprite.html` в корне проекта:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Иконки проекта</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<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 '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Запустите `npm run dev` и откройте `/svg-sprite.html`.
|
||||||
|
|
||||||
|
Viewer не требуется для работы `AppIcon` и не подключается к основному коду приложения.
|
||||||
126
skills/svg-sprites-ru/references/docs/ru/guides/vue-webpack.md
Normal file
126
skills/svg-sprites-ru/references/docs/ru/guides/vue-webpack.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# SVG-спрайт для Vue на Webpack 5
|
||||||
|
|
||||||
|
Инструкция по быстрому созданию SVG-спрайта в Vue-приложении на Webpack 5.
|
||||||
|
|
||||||
|
## Генерация спрайта
|
||||||
|
|
||||||
|
Выберите каталог для будущего SVG-спрайта, например `assets/app-icons`, и создайте в нём `svg-sprite.config.json`. В `input` укажите путь к существующим SVG относительно файла конфигурации. Перемещать или копировать иконки не требуется.
|
||||||
|
|
||||||
|
Пример конфига:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "vue@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет не нужно добавлять в зависимости проекта: генерация запускается через `npx`.
|
||||||
|
|
||||||
|
Добавьте команды генерации в `package.json`. Сгенерированные файлы по умолчанию исключены из Git, поэтому `predev` и `prebuild` пересобирают спрайт перед каждым запуском и сборкой:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование спрайта
|
||||||
|
|
||||||
|
Значение `name: "app"` создаёт Vue-компонент `AppIcon`. Создайте `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Используйте компонент в приложении:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Готово"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Свойство `icon` принимает имена исходных SVG без расширения. Монохромная иконка наследует `color`, а цвета многоцветной переопределяются через `--icon-color-N`.
|
||||||
|
|
||||||
|
Компонент использует CSS Modules. Если проект ещё не обрабатывает их, установите `style-loader` и `css-loader`, затем добавьте правило с default export:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev style-loader css-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.module\.css$/i,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: { modules: { namedExport: false } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 сам добавляет `sprite.svg` в итоговую сборку.
|
||||||
|
|
||||||
|
## Дебаг и превью
|
||||||
|
|
||||||
|
Viewer показывает все иконки на одной странице, позволяет проверить их отображение, изменить цвета и посмотреть связанные CSS-переменные. Он нужен только для разработки и устанавливается отдельно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Добавьте Viewer в Vue-компонент, подключаемый только при разработке:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
:sources="sources"
|
||||||
|
viewer-title="Иконки проекта"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Настройте Vue Loader так, чтобы `gromlab-sprite-viewer` считался custom element:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: 'vue-loader',
|
||||||
|
options: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Покажите компонент Viewer на странице разработки. Viewer не требуется для работы `AppIcon`.
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
# Программный API
|
||||||
|
|
||||||
|
[Индекс документации](../README.md)
|
||||||
|
|
||||||
|
Пакет распространяется как ESM и предоставляет единый Node.js API генерации. Framework-neutral Viewer находится в `@gromlab/svg-sprites/viewer`, auto-register entry — в `@gromlab/svg-sprites/viewer/element`, React bridge — в `@gromlab/svg-sprites/react`.
|
||||||
|
|
||||||
|
## `generateSprite`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { generateSprite } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
const result = await generateSprite(
|
||||||
|
'src/ui/file-manager/svg-sprite/svg-sprite.config.ts',
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат содержит имя и 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`. `standalone@server`
|
||||||
|
возвращает `target: 'server'`; его `spritePath` указывает на стандартный
|
||||||
|
content-addressed profile, а `manifestPath` — на server manifest.
|
||||||
|
|
||||||
|
Для static standalone mode `result.spritePath` можно использовать в build-скрипте,
|
||||||
|
чтобы опубликовать SVG по URL приложения:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { copyFile } from 'node:fs/promises'
|
||||||
|
|
||||||
|
const result = await generateSprite('src/sprite/svg-sprite.config.ts', {
|
||||||
|
mode: 'standalone',
|
||||||
|
})
|
||||||
|
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-модуля становится этот каталог.
|
||||||
|
|
||||||
|
Второй аргумент содержит необязательные overrides и всегда имеет приоритет над конфигом:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await generateSprite('src/ui/file-manager/svg-sprite/custom-config.json', {
|
||||||
|
mode: 'react@webpack',
|
||||||
|
name: 'documents',
|
||||||
|
input: ['./assets', '../../shared/search.svg'],
|
||||||
|
transform: {
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
generatedNotice: false,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Порядок разрешения настроек:
|
||||||
|
|
||||||
|
```text
|
||||||
|
defaults → config → API overrides
|
||||||
|
```
|
||||||
|
|
||||||
|
Для полностью программной генерации передайте каталог и все обязательные настройки через overrides:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await generateSprite('src/ui/file-manager/svg-sprite', {
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'file-manager',
|
||||||
|
input: [
|
||||||
|
'../../shared/search.svg',
|
||||||
|
'../../shared/settings.svg',
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Конфигурация
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'file-manager',
|
||||||
|
description: 'Иконки файлового менеджера',
|
||||||
|
input: ['./icons', '../../shared/check.svg'],
|
||||||
|
transform: {
|
||||||
|
removeSize: true,
|
||||||
|
replaceColors: true,
|
||||||
|
addTransition: true,
|
||||||
|
},
|
||||||
|
generatedNotice: true,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` принимает одну папку, SVG-файл или glob-паттерн либо массив, объединяющий такие источники. Если поле не задано, используется `./icons`; относительные пути считаются от папки с конфигом.
|
||||||
|
|
||||||
|
`defineSpriteConfig` является identity helper для TypeScript autocomplete. JS может экспортировать тот же объект через `export default`, а JSON содержит объект непосредственно.
|
||||||
|
|
||||||
|
Публичные типы `ServerSvgInput`, `ServerSpriteManifest`, `ServerSpriteAsset` и
|
||||||
|
`SpriteCompileProfile` описывают inputs и release data для `standalone@server`.
|
||||||
|
Consumer использует тот же API с `source: 'remote'` и одним local path или HTTP(S)
|
||||||
|
URL manifest в `input`.
|
||||||
|
|
||||||
|
## Специализированные обёртки
|
||||||
|
|
||||||
|
Специализированные функции доступны как обёртки над `generateSprite`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { generateNextSprite, generateReactSprite } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
await generateReactSprite('path/to/config.ts', 'vite')
|
||||||
|
await generateNextSprite('path/to/config.ts', {
|
||||||
|
router: 'app',
|
||||||
|
bundler: 'turbopack',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Явно переданный target перекрывает `mode` из файла. Для нового кода используйте `generateSprite`.
|
||||||
|
|
||||||
|
## Config API
|
||||||
|
|
||||||
|
```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`.
|
||||||
|
|
||||||
|
## Низкоуровневый compiler
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import {
|
||||||
|
compileSprite,
|
||||||
|
compileSpriteContent,
|
||||||
|
createShapeTransform,
|
||||||
|
} from '@gromlab/svg-sprites'
|
||||||
|
```
|
||||||
|
|
||||||
|
Эти функции предназначены для собственного orchestration. Стандартная генерация должна выполняться через `generateSprite`.
|
||||||
|
|
||||||
|
## Viewer runtime
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
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
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
```
|
||||||
|
|
||||||
|
`SpriteViewer` принимает generated manifests, remote standalone sources, lazy loaders или результат `import.meta.glob`. React entry содержит `'use client'` и предназначен для debug-инструментов; production-компоненты импортируются из локальных sprite-модулей приложения.
|
||||||
716
skills/svg-sprites-ru/references/docs/ru/reference/technical.md
Normal file
716
skills/svg-sprites-ru/references/docs/ru/reference/technical.md
Normal file
@@ -0,0 +1,716 @@
|
|||||||
|
# Технический справочник
|
||||||
|
|
||||||
|
[Индекс документации](../README.md)
|
||||||
|
|
||||||
|
[Конфигурация JSON, JavaScript и TypeScript](../configuration.md)
|
||||||
|
|
||||||
|
Справочник по конфигурации, generated API и поведению `@gromlab/svg-sprites`. Пошаговую установку смотрите в руководстве для вашего стека:
|
||||||
|
|
||||||
|
- [Bare standalone](../guides/standalone.md)
|
||||||
|
- [Standalone + Vite](../guides/standalone-vite.md)
|
||||||
|
- [Standalone + Webpack 5](../guides/standalone-webpack.md)
|
||||||
|
- [React + Vite](../guides/react-vite.md)
|
||||||
|
- [React + Webpack 5](../guides/react-webpack.md)
|
||||||
|
- [Next.js App Router + Turbopack](../guides/next-app-turbopack.md)
|
||||||
|
- [Next.js App Router + Webpack](../guides/next-app-webpack.md)
|
||||||
|
- [Next.js Pages Router + Turbopack](../guides/next-pages-turbopack.md)
|
||||||
|
- [Next.js Pages Router + Webpack](../guides/next-pages-webpack.md)
|
||||||
|
- [Vue + Vite](../guides/vue-vite.md)
|
||||||
|
- [Vue + Webpack](../guides/vue-webpack.md)
|
||||||
|
- [Nuxt + Vite](../guides/nuxt-vite.md)
|
||||||
|
- [Nuxt + Webpack](../guides/nuxt-webpack.md)
|
||||||
|
- [Svelte + Vite](../guides/svelte-vite.md)
|
||||||
|
- [Svelte + Webpack](../guides/svelte-webpack.md)
|
||||||
|
- [SvelteKit + Vite](../guides/sveltekit-vite.md)
|
||||||
|
- [Angular application builder](../guides/angular-application.md)
|
||||||
|
- [Angular + Webpack](../guides/angular-webpack.md)
|
||||||
|
- [Astro + Vite](../guides/astro-vite.md)
|
||||||
|
- [Solid + Vite](../guides/solid-vite.md)
|
||||||
|
- [Solid + Webpack](../guides/solid-webpack.md)
|
||||||
|
- [SolidStart + Vite](../guides/solid-start-vite.md)
|
||||||
|
- [Preact + Vite](../guides/preact-vite.md)
|
||||||
|
- [Preact + Webpack](../guides/preact-webpack.md)
|
||||||
|
- [Qwik + Vite](../guides/qwik-vite.md)
|
||||||
|
- [Lit + Vite](../guides/lit-vite.md)
|
||||||
|
- [Lit + Webpack](../guides/lit-webpack.md)
|
||||||
|
- [Alpine.js + Vite](../guides/alpine-vite.md)
|
||||||
|
- [Alpine.js + Webpack](../guides/alpine-webpack.md)
|
||||||
|
|
||||||
|
## Требования
|
||||||
|
|
||||||
|
- Node.js 18 или новее;
|
||||||
|
- пакет распространяется как ESM и подключается через `import`;
|
||||||
|
- React 18 или 19 требуется только для React/Next generated-компонентов и `@gromlab/svg-sprites/react`;
|
||||||
|
- для типизации package exports используйте TypeScript 5+ с `moduleResolution: "bundler"`, `"node16"` или `"nodenext"`.
|
||||||
|
|
||||||
|
Для генерации не нужна dependency проекта. Запускайте CLI через `npx`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Устанавливайте пакет как development dependency, только если проекту нужны
|
||||||
|
Viewer, типы конфига или программный API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI и режимы генерации
|
||||||
|
|
||||||
|
Для генерации CLI принимает ровно один путь: явно выбранный config-файл либо каталог для config-less генерации:
|
||||||
|
|
||||||
|
```text
|
||||||
|
svg-sprites [options] <config-file-or-directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Среда | Mode |
|
||||||
|
|---|---|
|
||||||
|
| Static HTML / собственная публикация | `standalone` |
|
||||||
|
| Standalone + Vite | `standalone@vite` |
|
||||||
|
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||||
|
| Server release | `standalone@server` |
|
||||||
|
| React + Vite | `react@vite` |
|
||||||
|
| React + Webpack 5 | `react@webpack` |
|
||||||
|
| Vue + Vite | `vue@vite` |
|
||||||
|
| Vue + Webpack | `vue@webpack` |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` |
|
||||||
|
| Svelte + Vite | `svelte@vite` |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` |
|
||||||
|
| Angular application builder | `angular@application` |
|
||||||
|
| Angular + Webpack | `angular@webpack` |
|
||||||
|
| Astro + Vite | `astro@vite` |
|
||||||
|
| Solid + Vite | `solid@vite` |
|
||||||
|
| Solid + Webpack | `solid@webpack` |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` |
|
||||||
|
| Preact + Vite | `preact@vite` |
|
||||||
|
| Preact + Webpack | `preact@webpack` |
|
||||||
|
| Qwik + Vite | `qwik@vite` |
|
||||||
|
| Lit + Vite | `lit@vite` |
|
||||||
|
| Lit + Webpack | `lit@webpack` |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||||
|
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||||
|
| 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.json`.
|
||||||
|
|
||||||
|
Если передан каталог, все настройки берутся из CLI. Если передан config-файл, CLI-параметры перекрывают значения файла. Общий порядок: `defaults → config → CLI`.
|
||||||
|
|
||||||
|
`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--source <local|remote>`, `--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 не раскрыл их до запуска генератора:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
svg-sprites --input './icons/**/*.svg' --input '!./icons/legacy/**' svg-sprite.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Mode должен соответствовать способу публикации приложения. Bare `standalone` оставляет публичный URL приложению; Vite и Webpack modes генерируют bundler-specific подключение SVG asset.
|
||||||
|
|
||||||
|
## Единая конфигурация
|
||||||
|
|
||||||
|
Каждый config-файл описывает один независимый спрайт.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'next@app/turbopack',
|
||||||
|
name: 'app',
|
||||||
|
description: 'Общие иконки приложения',
|
||||||
|
input: [
|
||||||
|
'./local-icons',
|
||||||
|
'../../assets/icons/*.svg',
|
||||||
|
'!../../assets/icons/deprecated-*.svg',
|
||||||
|
],
|
||||||
|
transform: {
|
||||||
|
removeSize: true,
|
||||||
|
replaceColors: true,
|
||||||
|
addTransition: true,
|
||||||
|
},
|
||||||
|
generatedNotice: true,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
| Опция | Тип | По умолчанию | Назначение |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `mode` | `SpriteMode` | Нет | Режим генерации; можно передать через CLI/API |
|
||||||
|
| `source` | `local \| remote` | `local` | Исходные SVG либо готовый server manifest |
|
||||||
|
| `name` | `string` | Выводится из каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и публичных типов |
|
||||||
|
| `description` | `string` | Нет | Описание для типов и debug manifest |
|
||||||
|
| `input` | `SpriteInput \| SpriteInput[]` | `./icons` | Локальные SVG sources, server HTTP descriptors либо один remote manifest в зависимости от mode и source |
|
||||||
|
| `transform` | `TransformOptions` | Все включены | Настройки подготовки SVG |
|
||||||
|
| `generatedNotice` | `boolean` | `true` | Полное или короткое предупреждение в generated-файлах |
|
||||||
|
|
||||||
|
При `source: 'remote'` поле `input` содержит один local path или HTTP(S) URL
|
||||||
|
manifest, созданного `standalone@server`. Remote consumer config может содержать
|
||||||
|
только `mode`, `source` и `input`: name, description, transforms и generated notice
|
||||||
|
проверяются и наследуются из server manifest. До codegen генератор скачивает profile,
|
||||||
|
необходимый exact consumer mode, и проверяет его SHA-256 и размер. Runtime-зависимости
|
||||||
|
от server manifest нет.
|
||||||
|
|
||||||
|
### Имя спрайта
|
||||||
|
|
||||||
|
`name` записывается в kebab-case и должно начинаться с латинской буквы:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app → AppIcon
|
||||||
|
file-manager → FileManagerIcon
|
||||||
|
```
|
||||||
|
|
||||||
|
Если `name` не задано, генератор преобразует имя каталога в kebab-case. Для каталога с именем `svg-sprite` или `svg-sprites` используется имя родительского каталога.
|
||||||
|
|
||||||
|
### Источники иконок
|
||||||
|
|
||||||
|
`SpriteConfig.input` является необязательным и имеет тип `string | string[]`. Если поле отсутствует, источником служит папка `./icons` относительно папки конфига. В config-less режиме относительные пути считаются от каталога, переданного CLI или API.
|
||||||
|
|
||||||
|
Каждая строка без префикса `!` может быть путём к конкретной папке, конкретному файлу `.svg` или glob-паттерном. Папка включает только непосредственные дочерние `*.svg`. Для рекурсивного обхода вложенных каталогов укажите явный паттерн, например `icons/**/*.svg`.
|
||||||
|
|
||||||
|
Массив объединяет все включающие источники. Паттерн с префиксом `!` глобально исключает совпадения из общего результата независимо от того, какой источник их добавил.
|
||||||
|
|
||||||
|
Поддерживается следующий glob-синтаксис:
|
||||||
|
|
||||||
|
| Синтаксис | Значение |
|
||||||
|
|---|---|
|
||||||
|
| `*` | Любые символы внутри одного сегмента пути |
|
||||||
|
| `**` | Любое число вложенных каталогов |
|
||||||
|
| `?` | Один символ внутри сегмента пути |
|
||||||
|
| `{a,b}` | Одна из альтернатив |
|
||||||
|
| `[abc]` | Один символ из набора или диапазона |
|
||||||
|
| `!pattern` | Исключение совпадений из всего объединённого input |
|
||||||
|
|
||||||
|
Каждый включающий источник или паттерн должен найти хотя бы один SVG, иначе генерация завершается ошибкой. Повторяющиеся пути удаляются, а итоговый список файлов детерминированно сортируется. Разные SVG с одинаковым basename по-прежнему считаются конфликтом, потому что basename задаёт публичное имя иконки.
|
||||||
|
|
||||||
|
### Server SVG inputs
|
||||||
|
|
||||||
|
`standalone@server` принимает те же local strings и HTTP(S) descriptors в массиве
|
||||||
|
`input`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
name: 'brand-logo',
|
||||||
|
url: 'https://assets.example.com/brand-logo.svg',
|
||||||
|
sha256: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`name` становится публичным именем иконки. Необязательный `sha256` проверяется по
|
||||||
|
скачанным байтам. URL credentials и активное SVG-содержимое, включая scripts,
|
||||||
|
event handlers, `foreignObject` и doctype, запрещены. Один HTTP source ограничен
|
||||||
|
2 MiB, все источники вместе — 25 MiB, timeout запроса равен 15 секундам. Local и
|
||||||
|
HTTP entries используют единое пространство имён, поэтому duplicate icon names
|
||||||
|
завершают генерацию с ошибкой.
|
||||||
|
|
||||||
|
## Generated-модуль
|
||||||
|
|
||||||
|
После генерации React- или Next.js-каталог спрайта выглядит так:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app-icons/
|
||||||
|
├── .gitignore
|
||||||
|
├── svg-sprite.config.json
|
||||||
|
├── index.ts # необязательный пользовательский barrel
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── index.js
|
||||||
|
├── index.d.ts
|
||||||
|
├── icon-data.js
|
||||||
|
├── icon-data.d.ts
|
||||||
|
├── sprite.svg
|
||||||
|
├── svg-sprite.manifest.js
|
||||||
|
├── svg-sprite.manifest.d.ts
|
||||||
|
└── react/
|
||||||
|
├── react-component.js
|
||||||
|
├── react-component.d.ts
|
||||||
|
└── react-component.module.css
|
||||||
|
```
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `.svg-sprite/index.js` | Mode-specific production facade и runtime-список имён |
|
||||||
|
| `.svg-sprite/index.d.ts` | Публичные декларации facade, компонента и union-типа имён |
|
||||||
|
| `.svg-sprite/svg-sprite.manifest.js` | Debug metadata и URL asset для `SpriteViewer` |
|
||||||
|
| `.svg-sprite/sprite.svg` | Собранный SVG-спрайт |
|
||||||
|
| `.svg-sprite/react/react-component.js` | Runtime React-компонента без TypeScript и JSX |
|
||||||
|
| `.svg-sprite/react/react-component.d.ts` | Props, style и declaration React-компонента |
|
||||||
|
| `.svg-sprite/react/react-component.module.css` | Стили конкретной React-реализации |
|
||||||
|
| `.svg-sprite/icon-data.js` | Runtime-список имён и внутренние IDs |
|
||||||
|
| `.svg-sprite/*.d.ts` | TypeScript-декларации соответствующих JS-модулей |
|
||||||
|
|
||||||
|
Standalone-контракты не создают каталог `react/`. Bare `standalone` содержит только
|
||||||
|
runtime asset и deployment-neutral manifest data:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.svg-sprite/
|
||||||
|
├── sprite.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`standalone@vite` и `standalone@webpack` дополнительно создают `index.*`,
|
||||||
|
`icon-data.*` и resolved `svg-sprite.manifest.*`. Их facade содержит нативный
|
||||||
|
generated Web Component без внешних runtime-зависимостей. Bare `standalone`
|
||||||
|
намеренно не создаёт JavaScript-компонент.
|
||||||
|
|
||||||
|
`standalone@server` создаёт готовый к публикации release без JavaScript runtime и
|
||||||
|
`.gitignore`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.svg-sprite/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Manifest описывает оба compile profiles через relative `href`, полный SHA-256 и
|
||||||
|
размер в байтах. Публикуйте весь каталог атомарно; consumer разрешает каждый profile
|
||||||
|
относительно URL или local path manifest.
|
||||||
|
|
||||||
|
`.svg-sprite` полностью управляется генератором и при каждой генерации заменяется целиком. Любые добавленные в него файлы будут удалены. Пользовательские файлы размещайте рядом, например в корневом `index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Standalone Web Component и TypeScript
|
||||||
|
|
||||||
|
В modes `standalone@vite` и `standalone@webpack` спрайт с `name: 'app'`
|
||||||
|
экспортирует функцию регистрации `defineAppIconElement()` и tag `<app-icon>`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '@/ui/app-icons'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
После регистрации элемент можно использовать в HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="search" aria-hidden="true"></app-icon>
|
||||||
|
|
||||||
|
<app-icon
|
||||||
|
icon="settings"
|
||||||
|
role="img"
|
||||||
|
aria-label="Настройки"
|
||||||
|
></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент рендерит `<svg><use>` в открытом Shadow DOM, сам выбирает внутренний
|
||||||
|
ID и `viewBox`, а URL asset получает через соответствующий Vite или Webpack
|
||||||
|
механизм. Размер host по умолчанию равен `1em × 1em`; `class`, `style`, `color`
|
||||||
|
и `--icon-color-N` задаются обычным CSS.
|
||||||
|
|
||||||
|
Generated `HTMLElementTagNameMap` типизирует property API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const icon = document.createElement('app-icon')
|
||||||
|
|
||||||
|
icon.icon = 'search'
|
||||||
|
icon.icon = 'unknown' // ошибка TypeScript
|
||||||
|
```
|
||||||
|
|
||||||
|
Значения атрибутов в обычной HTML-разметке TypeScript не проверяет. Поэтому
|
||||||
|
неизвестный `icon="unknown"` дополнительно проверяется в runtime: компонент
|
||||||
|
скрывает внутренний SVG и сообщает об ошибке, не создавая fragment
|
||||||
|
`#undefined`. Повторный вызов `defineAppIconElement()` безопасен для того же
|
||||||
|
спрайта; конфликт с другим элементом под tag `<app-icon>` завершается ошибкой.
|
||||||
|
|
||||||
|
## React-компонент и TypeScript
|
||||||
|
|
||||||
|
Спрайт с `name: 'app'` экспортирует:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export { AppIcon, appIconNames }
|
||||||
|
export type { AppIconName, AppIconProps, AppIconStyle }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Имена иконок
|
||||||
|
|
||||||
|
Имена SVG-файлов становятся допустимыми значениями `icon`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" />
|
||||||
|
<AppIcon icon="unknown" /> // ошибка TypeScript
|
||||||
|
```
|
||||||
|
|
||||||
|
Runtime-список содержит те же значения:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { appIconNames } from '@/ui/app-icons'
|
||||||
|
|
||||||
|
// readonly ['search', 'settings', 'user']
|
||||||
|
```
|
||||||
|
|
||||||
|
Имена с пробелами и другими небезопасными для SVG ID символами остаются частью публичного API. Для внутреннего fragment ID генератор создаёт стабильный безопасный hash:
|
||||||
|
|
||||||
|
```text
|
||||||
|
folder open.svg → icon="folder open" → id="icon-<stable-hash>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Для таких имён используйте generated-компонент или `id` из debug manifest, а не формируйте fragment ID вручную.
|
||||||
|
|
||||||
|
### SVG-атрибуты
|
||||||
|
|
||||||
|
По умолчанию компонент рендерит `<svg>` и принимает стандартные SVG-атрибуты:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="search"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
color="rebeccapurple"
|
||||||
|
className="searchIcon"
|
||||||
|
aria-label="Поиск"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Компонент не добавляет accessibility-семантику автоматически. Передавайте подходящие `aria-*`, `role` или подпись в зависимости от назначения иконки.
|
||||||
|
|
||||||
|
### Обёртка
|
||||||
|
|
||||||
|
`wrapped` рендерит `<span>` с внутренним SVG. Остальные props в этом режиме относятся к `<span>`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Типизированные CSS-переменные
|
||||||
|
|
||||||
|
`AppIconStyle` расширяет `CSSProperties` и поддерживает свойства вида `--icon-color-N`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="user"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#2563eb',
|
||||||
|
'--icon-color-2': '#dbeafe',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Множественные спрайты
|
||||||
|
|
||||||
|
Каждый каталог с конфигом создаёт независимый mode-specific контракт. Framework modes создают нативный компонент и declarations, standalone bundler modes — Web Component и declarations, а bare `standalone` — SVG и JSON manifest:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app-icons → AppIcon → общие иконки
|
||||||
|
analytics-icons → AnalyticsIcon → иконки страницы аналитики
|
||||||
|
editor-icons → EditorIcon → иконки редактора
|
||||||
|
```
|
||||||
|
|
||||||
|
Один исходный SVG можно добавить через `input` в несколько конфигураций. Копировать файл в каталоги каждого спрайта не требуется.
|
||||||
|
|
||||||
|
Для нескольких спрайтов добавьте отдельную CLI-команду для каждого каталога или объедините команды в общем npm script.
|
||||||
|
|
||||||
|
## Форматы и способы отображения
|
||||||
|
|
||||||
|
Все текущие modes создают формат `stack`.
|
||||||
|
|
||||||
|
| Формат | `<svg><use>` | `<img>` | CSS background |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| `stack` | Да | Да | Да |
|
||||||
|
|
||||||
|
### Generated-компонент
|
||||||
|
|
||||||
|
Используйте generated native-компонент из guide выбранного exact mode. Он знает внутренние ID, формирует URL и предоставляет TypeScript API. Для React и Next.js это выглядит так:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" width={24} height={24} />
|
||||||
|
```
|
||||||
|
|
||||||
|
Для `standalone@vite` и `standalone@webpack` используйте generated Web Component:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="search" style="font-size: 24px"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Вручную через `<svg><use>`
|
||||||
|
|
||||||
|
Способ получения `spriteUrl` зависит от сборщика.
|
||||||
|
|
||||||
|
Static HTML после публикации `.svg-sprite/sprite.svg` приложением:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg aria-hidden="true">
|
||||||
|
<use href="/assets/icons.svg#search"></use>
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Standalone Vite/Webpack предоставляет generated `getAppIconHref()` и mapping
|
||||||
|
внутренних IDs. Не конструируйте fragment из небезопасного имени файла вручную.
|
||||||
|
|
||||||
|
Vite:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import spriteUrl from './.svg-sprite/sprite.svg?no-inline'
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5, Turbopack и Next.js:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const spriteUrl = new URL('./.svg-sprite/sprite.svg', import.meta.url).href
|
||||||
|
```
|
||||||
|
|
||||||
|
После получения URL используйте его в JSX:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<svg width="24" height="24" aria-label="Поиск">
|
||||||
|
<use href={`${spriteUrl}#search`} />
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Для имён, небезопасных как SVG ID, используйте внутренний `id` из manifest.
|
||||||
|
|
||||||
|
### Через `<img>`
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<img src={`${spriteUrl}#search`} width={24} height={24} alt="Поиск" />
|
||||||
|
```
|
||||||
|
|
||||||
|
SVG внутри `<img>` изолирован от CSS страницы. `color` и `--icon-color-N` на внешнем элементе не изменяют его внутренние цвета.
|
||||||
|
|
||||||
|
### Через CSS
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
background: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Для одноцветного силуэта можно использовать mask:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
background-color: currentColor;
|
||||||
|
mask: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Mask не сохраняет исходные цвета, gradients и различия между `fill` и `stroke`.
|
||||||
|
|
||||||
|
Путь в CSS разрешается относительно самого CSS-файла. В примерах CSS-файл находится рядом с `svg-sprite.config.ts`.
|
||||||
|
|
||||||
|
## Assets и кеширование
|
||||||
|
|
||||||
|
Generated component или standalone facade передаёт SVG сборщику как отдельный asset:
|
||||||
|
|
||||||
|
- Vite использует статический импорт с `?no-inline`;
|
||||||
|
- Webpack 5, Turbopack и Next.js используют `new URL(..., import.meta.url)`;
|
||||||
|
- SVG path-данные не сериализуются в generated JavaScript.
|
||||||
|
|
||||||
|
Bare `standalone` не участвует в asset pipeline: приложение само копирует или
|
||||||
|
публикует `sprite.svg` и отвечает за URL, версионирование и cache policy.
|
||||||
|
|
||||||
|
При стандартном именовании assets сборщик добавляет content hash:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/assets/sprite-<hash>.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
Это позволяет кешировать SVG отдельно от JavaScript. Изменение React-кода не меняет содержимое спрайта, а изменение иконок создаёт новую версию asset.
|
||||||
|
|
||||||
|
HTTP cache headers, CDN и `Cache-Control` настраиваются приложением или платформой размещения. Для Webpack имя итогового файла зависит от `assetModuleFilename` проекта.
|
||||||
|
|
||||||
|
## Трансформации SVG
|
||||||
|
|
||||||
|
Все трансформации включены по умолчанию и настраиваются независимо:
|
||||||
|
|
||||||
|
| Опция | Что делает |
|
||||||
|
|---|---|
|
||||||
|
| `removeSize` | Удаляет `width` и `height` с корневого `<svg>`, сохраняя существующий `viewBox` |
|
||||||
|
| `replaceColors` | Заменяет найденные `fill` и `stroke` на `--icon-color-N` |
|
||||||
|
| `addTransition` | Добавляет transitions для `fill` и `stroke` в цветные элементы и generated styles |
|
||||||
|
|
||||||
|
Чтобы отключить отдельную операцию:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'next@app/turbopack',
|
||||||
|
transform: {
|
||||||
|
removeSize: false,
|
||||||
|
replaceColors: false,
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Исходные SVG не изменяются. Трансформации применяются только к содержимому generated-спрайта.
|
||||||
|
|
||||||
|
## Управление цветами
|
||||||
|
|
||||||
|
### Монохромные иконки
|
||||||
|
|
||||||
|
Если найден один цвет, fallback становится `currentColor`:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
stroke="var(--icon-color-1, currentColor)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Цвет задаётся через prop или CSS:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" color="rebeccapurple" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Многоцветные иконки
|
||||||
|
|
||||||
|
Каждый уникальный цвет получает отдельную переменную с исходным fallback:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
fill="var(--icon-color-1, #798198)"
|
||||||
|
fill="var(--icon-color-2, #ffffff)"
|
||||||
|
fill="var(--icon-color-3, #129d9d)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Можно заменить только необходимые значения:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
--icon-color-1: #4b5563;
|
||||||
|
--icon-color-3: #14b8a6;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ограничения
|
||||||
|
|
||||||
|
- `none`, `transparent`, `inherit`, `unset` и `initial` не заменяются;
|
||||||
|
- надёжнее всего обрабатываются цвета в атрибутах `fill`, `stroke` и inline `style`;
|
||||||
|
- CSS-классы и внешние stylesheets внутри SVG не являются основным сценарием трансформации;
|
||||||
|
- значения `url(#...)` могут быть заменены вместе с цветами, поэтому gradients и patterns требуют отдельного спрайта с `replaceColors: false`;
|
||||||
|
- masks, filters и сложные внутренние CSS-правила требуют визуальной проверки;
|
||||||
|
- CSS-переменные страницы доступны через `<svg><use>`, но не внутри `<img>` и CSS background.
|
||||||
|
|
||||||
|
Для сложной иконки можно отключить `replaceColors` в конфигурации отдельного спрайта.
|
||||||
|
|
||||||
|
## SpriteViewer
|
||||||
|
|
||||||
|
Viewer использует один Web Component с Shadow DOM для всех modes. React и будущие framework-компоненты являются bridge к этому же элементу, поэтому визуал и поведение не дублируются.
|
||||||
|
|
||||||
|
Bare `standalone` подключает самостоятельный browser bundle и передаёт URL JSON manifest и опубликованного SVG:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="https://unpkg.com/@gromlab/svg-sprites@<version>/dist/viewer-element.js"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
viewer-title="Иконки проекта"
|
||||||
|
manifest-url="/app-icons/manifest.json"
|
||||||
|
sprite-url="/app-icons/sprite.svg"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
`viewer-element.js` не имеет дополнительных runtime-файлов и может быть скопирован с остальными static assets для self-hosting.
|
||||||
|
|
||||||
|
`standalone@vite` и `standalone@webpack` регистрируют тот же элемент через npm entry и передают generated JS manifest через свойство `sources`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from './svg-sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
React и Next.js сохраняют компонентный API:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
```
|
||||||
|
|
||||||
|
Он принимает готовые manifests, remote standalone sources, массив lazy loaders или record формата `import.meta.glob`.
|
||||||
|
|
||||||
|
Vite:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = import.meta.glob<SpriteManifestModule>(
|
||||||
|
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||||
|
)
|
||||||
|
|
||||||
|
export const IconsDebugPage = () => (
|
||||||
|
<SpriteViewer sources={sources} title="Иконки проекта" />
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack и Next.js:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const sources = [
|
||||||
|
() => import('@/ui/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
() => import('@/features/analytics/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
export const IconsDebugPage = () => (
|
||||||
|
<SpriteViewer sources={sources} />
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Viewer показывает группы, поиск, `viewBox`, CSS-переменные и fallback-цвета. Framework manifests получают вкладку своего framework, а также SVG, IMG и CSS; standalone manifests получают SVG, IMG и CSS. Цветовые значения можно менять в интерфейсе и сразу проверять результат.
|
||||||
|
|
||||||
|
### Тема Viewer
|
||||||
|
|
||||||
|
По умолчанию `colorTheme="auto"` следует `prefers-color-scheme`. Можно передать `light` или `dark` явно:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<SpriteViewer sources={sources} colorTheme="dark" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Для синхронизации с темой приложения:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<SpriteViewer
|
||||||
|
sources={sources}
|
||||||
|
colorTheme={appTheme}
|
||||||
|
onColorThemeChange={setAppTheme}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites/react` содержит `'use client'` и рендерит Web Component host; внутренний Shadow DOM создаётся после загрузки browser runtime. В Next.js App Router размещайте Viewer внутри отдельной Client Component boundary и используйте только на debug-маршруте или во внутреннем инструменте.
|
||||||
|
|
||||||
|
## Generated-файлы, Git и CI
|
||||||
|
|
||||||
|
Все modes, кроме bare `standalone`, создают локальный `.gitignore` для:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/.svg-sprite/
|
||||||
|
```
|
||||||
|
|
||||||
|
Локальный `.gitignore` следует один раз добавить в репозиторий. Он исключает остальные generated-файлы, поэтому генерацию нужно запускать перед командами, которые импортируют sprite-модуль:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
CI должен выполнять generation script до сборки или проверки типов. Локальная установка package не нужна, если CI не использует Viewer, package-типы config или программный API.
|
||||||
|
|
||||||
|
Bare `standalone` не создаёт `.gitignore` и сохраняет пользовательский файл. Если после другого mode остался управляемый `.gitignore`, bare mode удалит его. В остальных modes генератор откажется перезаписать пользовательский `.gitignore` без generated marker. Корневой `index.ts` остаётся пользовательским и может переэкспортировать generated API.
|
||||||
|
|
||||||
|
## Диагностика
|
||||||
|
|
||||||
|
- Для всех 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`: в корне 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 не видит спрайт: для 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).
|
||||||
359
skills/svg-sprites/SKILL.md
Normal file
359
skills/svg-sprites/SKILL.md
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
---
|
||||||
|
name: svg-sprites
|
||||||
|
description: "Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes for standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit, or Alpine.js, SpriteConfig.input, --input, SpriteViewer, or --icon-color-N. Do NOT use for custom SVG sprites, favicons, raster images, icon fonts, choosing an icon set, or inline SVG without this package."
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Generated from src/skills/svg-sprites/src/en/SKILL.md. Do not edit manually. -->
|
||||||
|
|
||||||
|
# @gromlab/svg-sprites
|
||||||
|
|
||||||
|
## What the package does
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` is a CLI generator that builds SVG sprites from user-provided SVG files. The package does not include its own icon set: it compiles project SVGs into an external sprite asset and creates a typed native component for the selected exact framework and bundler mode.
|
||||||
|
|
||||||
|
The package supports multiple independent sprites in one project. Each explicitly selected config file or config-less directory describes one sprite and gets its own:
|
||||||
|
|
||||||
|
- SVG asset;
|
||||||
|
- mode-specific manifest data;
|
||||||
|
- icon name types and production entry `.svg-sprite/index.js` for every mode except bare `standalone`;
|
||||||
|
- an isolated framework-native component and declarations for framework modes;
|
||||||
|
- a native Web Component with an explicit registration function for `standalone@vite`/`standalone@webpack`;
|
||||||
|
- a deployment-neutral JSON manifest without a public URL for bare `standalone`.
|
||||||
|
- a content-addressed server release with two compile profiles and an integrity manifest for `standalone@server`.
|
||||||
|
|
||||||
|
The project determines how many sprite directories exist and where they live. For example, `name: 'file-manager'` produces `FileManagerIcon`, `FileManagerIconName`, and `fileManagerIconNames`, while another directory with `name: 'navigation'` produces a separate `NavigationIcon`. These are examples of per-sprite APIs, not fixed package exports.
|
||||||
|
|
||||||
|
Generated production runtime and declarations do not import `@gromlab/svg-sprites`. Generation through `npx --yes @gromlab/svg-sprites <path-to-config>` does not add the package to the project. Install it as a development dependency only for the Viewer, package-provided config types, or the programmatic API.
|
||||||
|
|
||||||
|
Any consumer exact mode can use `source: 'remote'` with one local path or HTTP(S)
|
||||||
|
URL to a manifest produced by `standalone@server`. Generation verifies and downloads
|
||||||
|
the required profile before the adapter creates its normal local API and asset; the
|
||||||
|
browser never depends on the server manifest at runtime.
|
||||||
|
|
||||||
|
## Selecting a mode
|
||||||
|
|
||||||
|
Select exactly one supported mode key:
|
||||||
|
|
||||||
|
| Project | Mode key |
|
||||||
|
|---|---|
|
||||||
|
| Static HTML / custom publishing | `standalone` |
|
||||||
|
| Standalone + Vite | `standalone@vite` |
|
||||||
|
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||||
|
| Server or CI release | `standalone@server` |
|
||||||
|
| React + Vite | `react@vite` |
|
||||||
|
| React + Webpack 5 | `react@webpack` |
|
||||||
|
| Vue + Vite | `vue@vite` |
|
||||||
|
| Vue + Webpack | `vue@webpack` |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` |
|
||||||
|
| Svelte + Vite | `svelte@vite` |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` |
|
||||||
|
| Angular application builder | `angular@application` |
|
||||||
|
| Angular + Webpack | `angular@webpack` |
|
||||||
|
| Astro + Vite | `astro@vite` |
|
||||||
|
| Solid + Vite | `solid@vite` |
|
||||||
|
| Solid + Webpack | `solid@webpack` |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` |
|
||||||
|
| Preact + Vite | `preact@vite` |
|
||||||
|
| Preact + Webpack | `preact@webpack` |
|
||||||
|
| Qwik + Vite | `qwik@vite` |
|
||||||
|
| Lit + Vite | `lit@vite` |
|
||||||
|
| Lit + Webpack | `lit@webpack` |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||||
|
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||||
|
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||||
|
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||||
|
|
||||||
|
Mode may come from the config, CLI, or programmatic API. Values are applied as `defaults → config → CLI/API overrides`. A mode must exist after merging.
|
||||||
|
|
||||||
|
`name` is optional. When omitted, the generator converts the sprite-module directory name to kebab-case; directories named `svg-sprite` and `svg-sprites` use their parent directory's name. An explicit `name` must already be kebab-case and begin with an ASCII letter.
|
||||||
|
|
||||||
|
The CLI accepts exactly one path. A `.ts`, `.js`, or `.json` file loads that exact config regardless of its name. A directory enables config-less generation with settings supplied through CLI flags.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprite:<name>": "npx --yes @gromlab/svg-sprites <path-to-config>",
|
||||||
|
"sprite:<name>:cli": "npx --yes @gromlab/svg-sprites --mode <mode-key> <sprite-directory>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Generation through `npx` does not add the package to the project. Do not invent shortened or generic mode keys, and do not use the removed `legacy` mode. Select one complete key from the table. Use bare `standalone` only when the application publishes the SVG itself, and `standalone@server` only for a centralized release consumed during generation. Create one command per config file or directory when the project has multiple sprites.
|
||||||
|
|
||||||
|
## Inspecting the project
|
||||||
|
|
||||||
|
Establish the project's actual contract before making changes:
|
||||||
|
|
||||||
|
1. Read the root `package.json`, lockfile, and workspace configuration; identify the framework, bundler, and existing commands.
|
||||||
|
2. Find config files, commands containing `svg-sprites`, and imports of generated components. Config names are arbitrary; use the explicit CLI path and object fields.
|
||||||
|
3. Determine the framework, router when applicable, and actual bundler from scripts and configuration. For Next.js, separately determine the App/Pages Router and the bundler used by the real `dev`/`build` commands.
|
||||||
|
4. Check existing `predev`, `prebuild`, `pretypecheck`, and orchestration scripts. Do not overwrite them.
|
||||||
|
5. For a new sprite, choose a target directory without imposing a particular application layer or architecture.
|
||||||
|
6. Check TypeScript and alias settings. Package subpath exports require TypeScript 5+ with `moduleResolution: 'bundler'`, `'node16'`, or `'nodenext'`.
|
||||||
|
|
||||||
|
For a regular local consumer, all input paths are relative to the directory containing the explicitly selected config file; in config-less mode they are relative to the supplied directory. Inspect local `input` using this contract:
|
||||||
|
|
||||||
|
- `input?: string | string[]` defaults to `./icons`;
|
||||||
|
- each string is a folder, an exact SVG file, or a glob;
|
||||||
|
- a folder is scanned shallowly; nested files are included only by an explicit recursive glob such as `./icons/**/*.svg`;
|
||||||
|
- an array combines positive sources, while an item prefixed with `!` excludes its matches from the combined set;
|
||||||
|
- every positive source must resolve to at least one SVG, so a missing or empty folder, an unmatched glob, a missing file, or a non-SVG exact file is an error;
|
||||||
|
- resolved files are deduplicated and sorted deterministically;
|
||||||
|
- different files with the same basename are a conflict, even when they came from different sources.
|
||||||
|
|
||||||
|
Branch before applying those rules:
|
||||||
|
|
||||||
|
- `standalone@server` may combine local strings with `{ name, url, sha256? }` HTTP(S) descriptors; `name` is the public icon name and optional `sha256` verifies the downloaded bytes;
|
||||||
|
- `source: 'remote'` requires exactly one string containing a local manifest path or HTTP(S) manifest URL and does not accept source globs or descriptors;
|
||||||
|
- a remote consumer config contains only `mode`, `source`, and `input`; name, description, transforms, and generated notice come from the verified server manifest.
|
||||||
|
|
||||||
|
Do not copy a shared SVG into several folders: add its exact path or a suitable glob to `input` in every sprite that needs it. Use `**/*.svg` only when recursive inclusion is intentional.
|
||||||
|
|
||||||
|
## Setting up the integration
|
||||||
|
|
||||||
|
Do not reproduce mode setup from memory. After inspecting the project, select one exact mode and open the corresponding file under `references/docs/en/guides/`. Treat that guide as the base operational contract, then adapt it to the project's existing structure.
|
||||||
|
|
||||||
|
Work in this order:
|
||||||
|
|
||||||
|
1. Identify the source SVG directory and the directory for one sprite module. One config creates one independent sprite; multiple sets require separate config files and unique `name` values.
|
||||||
|
2. Confirm the framework, router, and bundler against the exact mode. For Next.js, inspect the actual `dev` and `build` scripts, not just the presence of `next.config.*`.
|
||||||
|
3. Prefer a JSON config when the project does not need package-provided config types. A TypeScript config also loads through the CLI, but the package must be installed when the config imports `defineSpriteConfig` or package types.
|
||||||
|
4. Resolve every `input` from the config-file directory. Do not reorganize SVGs unnecessarily: use a folder path, exact file, glob, or array of these sources.
|
||||||
|
5. Add a sprite command with an explicit config path. Preserve existing `dev`, `build`, `typecheck`, and lifecycle hooks; place generation before the first process that imports `.svg-sprite`.
|
||||||
|
6. Do not run one generation twice through both a concurrent `predev` and `npm run sprites && ...`. For multiple sprites, create separate commands and one aggregate script.
|
||||||
|
7. If the application imports the sprite-module directory, create a user-owned `index.ts` next to `.svg-sprite`; do not place user files inside the generated directory.
|
||||||
|
8. Run the first generation before typecheck or application startup, then inspect the mode-specific output and the actual component import.
|
||||||
|
|
||||||
|
For a centralized release, open `references/docs/en/guides/standalone-server.md`.
|
||||||
|
Generate and publish the complete `.svg-sprite` directory atomically. In each consumer,
|
||||||
|
retain its own exact framework mode, set `source: 'remote'`, and point `input` to that
|
||||||
|
manifest. Do not copy server files into a framework output or fetch the manifest from
|
||||||
|
application runtime.
|
||||||
|
|
||||||
|
Do not add the Viewer automatically. Connect it only when requested or when visual verification of the set, colors, or complex SVGs is needed. Get the production isolation pattern from the exact guide: frameworks, bundlers, and routers use different boundaries.
|
||||||
|
|
||||||
|
Do not copy snippets between exact modes even when their APIs look similar. Asset URLs, generated files, CSS handling, router boundaries, and debug-tool setup differ.
|
||||||
|
|
||||||
|
## Generated directory contract
|
||||||
|
|
||||||
|
For example, after generation a React/Next.js directory has this structure:
|
||||||
|
|
||||||
|
```text
|
||||||
|
svg-sprite/
|
||||||
|
├── icons/ # user-owned sources
|
||||||
|
├── svg-sprite.config.json # recommended config name
|
||||||
|
├── index.ts # optional user-owned barrel
|
||||||
|
├── .gitignore # managed by the generator
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── index.js
|
||||||
|
├── index.d.ts
|
||||||
|
├── icon-data.js
|
||||||
|
├── icon-data.d.ts
|
||||||
|
├── sprite.svg
|
||||||
|
├── svg-sprite.manifest.js
|
||||||
|
├── svg-sprite.manifest.d.ts
|
||||||
|
└── react/
|
||||||
|
├── react-component.js
|
||||||
|
├── react-component.d.ts
|
||||||
|
└── react-component.module.css
|
||||||
|
```
|
||||||
|
|
||||||
|
Standalone modes do not create `react/`. Bare `standalone` generates `sprite.svg` and `svg-sprite.manifest.json`; `standalone@vite`/`standalone@webpack` additionally generate `index.*`, `icon-data.*`, and a resolved manifest. Their `index.*` also contains a native generated Web Component; bare `standalone` gets no JavaScript runtime and does not create `.gitignore`.
|
||||||
|
|
||||||
|
`standalone@server` generates `sprite.<content-hash>.svg`,
|
||||||
|
`sprite-root-viewbox.<content-hash>.svg`, and `svg-sprite.manifest.json`. It has no
|
||||||
|
consumer facade, browser runtime, Viewer entry, or `.gitignore`. The manifest records
|
||||||
|
both relative profile URLs, full SHA-256 digests, byte lengths, icon metadata, and
|
||||||
|
transform settings.
|
||||||
|
|
||||||
|
Edit the source SVGs, selected config, and user-owned `index.ts`. Do not manually change anything in `.svg-sprite`: the next generation will overwrite it. In every mode except bare `standalone`, the generated `.gitignore` is also managed by the generator. To import from the sprite-module root, create a barrel:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator owns the complete `.svg-sprite` directory and replaces it on every run. Never put user files inside it. The generator also owns `.gitignore` when the selected mode creates it. Bare `standalone` preserves a user-owned `.gitignore`, but removes a managed `.gitignore` left by another mode. Generated paths must not contain symlinks.
|
||||||
|
|
||||||
|
Every exact-mode adapter owns its facade, framework directory, native component runtime, declarations, manifest source, styles, and asset URL. React/Next use `react/`; other framework modes use their own generated contract documented by the matching guide. Standalone bundler modes export Web Component helpers and types; bare `standalone` does not create a facade. Manifest declarations define their types locally and do not import the generator package.
|
||||||
|
|
||||||
|
In bundler modes, the sprite remains a separate asset and SVG path data is not embedded in JavaScript. The content hash depends on bundler settings. Bare `standalone` creates a fixed filename, and the application owns its public name and versioning:
|
||||||
|
|
||||||
|
- Vite-based adapters use a mode-owned static asset import that keeps the sprite external;
|
||||||
|
- `standalone@vite` uses the same Vite asset mechanism and exports an href helper plus a native Web Component without React;
|
||||||
|
- `standalone@webpack` uses Webpack Asset Modules and exports the same mode-local Web Component without React;
|
||||||
|
- Webpack-based adapters and all Next modes use their adapter-owned external asset mechanism, commonly `new URL(..., import.meta.url).href`;
|
||||||
|
- a custom Webpack SVG loader must not intercept the generated `sprite.svg`;
|
||||||
|
- in Next mode, the generated component does not contain `'use client'` and works in Server Components, SSR, and SSG; do not add a client boundary solely for an icon;
|
||||||
|
- the Next build command and mode key must agree: Turbopack with `.../turbopack`, Webpack with `.../webpack`.
|
||||||
|
- remote consumers still publish through their own adapter's local asset pipeline; do not preserve or construct the server profile URL in generated application code.
|
||||||
|
|
||||||
|
For bundler modes, do not move the generated sprite into `public` or rewrite its URL manually. For bare `standalone`, do not move the managed original: the application may explicitly copy it into deploy output and owns the public URL and stale-copy cleanup. Regenerate with the new complete key when changing mode.
|
||||||
|
|
||||||
|
## Usage, accessibility, and colors
|
||||||
|
|
||||||
|
The component name depends on the specific sprite's `name`. In `standalone@vite` and `standalone@webpack`, `name: 'file-manager'` creates the `<file-manager-icon>` tag and the `defineFileManagerIconElement()` function:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineFileManagerIconElement } from './svg-sprite'
|
||||||
|
|
||||||
|
defineFileManagerIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<file-manager-icon icon="folder" aria-hidden="true"></file-manager-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
The native element has no runtime dependencies, selects the generated ID and `viewBox`, obtains the URL through the bundler, and renders `<svg><use>` in Shadow DOM. Its `icon` property is typed with the exact name union, while plain HTML attribute values are validated only at runtime. It defaults to `1em × 1em`; resize the host with CSS. Bare `standalone` does not generate a Web Component.
|
||||||
|
|
||||||
|
In component modes, the same `name: 'file-manager'` creates a native `FileManagerIcon` component. Its syntax and props follow the exact-mode guide. For React/Next.js, `name: 'navigation'` creates `NavigationIcon`.
|
||||||
|
|
||||||
|
Import the component from the root of its sprite directory. `width` and `height` are optional: ordinary CSS classes can control the size.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { FileManagerIcon } from './svg-sprite'
|
||||||
|
|
||||||
|
export const OpenButton = () => (
|
||||||
|
<button type="button">
|
||||||
|
<FileManagerIcon icon="folder" className="icon" aria-hidden="true" />
|
||||||
|
<span>Open</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: #4b5563;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`icon` accepts exact source filenames without `.svg`; an unknown name is a TypeScript error. For names that are not safe SVG IDs, the generator preserves the public name but creates an internal stable hash ID, so do not construct a fragment URL from the name manually.
|
||||||
|
|
||||||
|
By default, the component renders `<svg>` and accepts standard SVG attributes: optional `width`/`height`, `className`, `style`, `role`, `aria-*`, and event handlers. With `wrapped={true}`, the root becomes a `<span>`, props apply to the span, and the inner SVG fills the wrapper.
|
||||||
|
|
||||||
|
The generated component does not decide semantics for the application and does not add a `title`. For a decorative icon, pass `aria-hidden="true"`; for a standalone meaningful icon, pass `role="img"` and an accessible name through `aria-label`. Do not duplicate the name when adjacent text already announces the action. Put interactivity on a `button` or `a`, not on the icon itself.
|
||||||
|
|
||||||
|
The `removeSize`, `replaceColors`, and `addTransition` transforms are enabled by default. A monochrome icon's only color gets a `currentColor` fallback, so control it with the CSS `color` property. For a multicolor icon, pass typed custom properties:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon
|
||||||
|
icon="folder"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#4b5563',
|
||||||
|
'--icon-color-2': '#14b8a6',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Automatic replacement targets `fill`/`stroke` attributes and inline `style`. The values `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced. Check CSS classes and external stylesheets, gradients, patterns, filters, and `url(#...)` against the actual output. Page variables work through `<svg><use>`, but do not cross into an external document loaded through `<img>` or `background-image`; a CSS mask preserves only a monochrome silhouette.
|
||||||
|
|
||||||
|
`SpriteViewer` is optional. Install `@gromlab/svg-sprites` as a development dependency only when the project needs the Viewer. It accepts manifests or statically discoverable loaders and provides search, themes, colors, and examples, but production components do not depend on it.
|
||||||
|
|
||||||
|
Open the exact guide before connecting the Viewer. Frameworks, bundlers, and routers require different debug entries or client boundaries. Do not transfer setup between modes.
|
||||||
|
|
||||||
|
## Verifying the result
|
||||||
|
|
||||||
|
After changing a config or SVG, perform these required checks:
|
||||||
|
|
||||||
|
1. Run the exact sprite command. It must exit with code `0` and report the name, icon count, mode, and `.svg-sprite` directory.
|
||||||
|
2. Inspect the output for the selected exact mode:
|
||||||
|
- bare `standalone` creates `sprite.svg` and `svg-sprite.manifest.json`;
|
||||||
|
- `standalone@server` creates two content-addressed SVG profiles and a server manifest whose hashes and relative paths match those files;
|
||||||
|
- `standalone@vite` and `standalone@webpack` additionally create `index.*`, `icon-data.*`, and a JS manifest, but no `react/` directory;
|
||||||
|
- framework modes also create their adapter-owned native component runtime, declaration, and styles.
|
||||||
|
3. For modes with a public facade, inspect `.svg-sprite/index.js`, the adjacent `index.d.ts`, the name list, and the actual import through the user-owned barrel.
|
||||||
|
4. Inspect the manifest: mode and target must match the selected adapter, and the icon list must match the source SVGs. In bundler modes the URL must use the mode-specific mechanism; the bare JSON manifest intentionally has no public `spriteUrl`.
|
||||||
|
5. Run the project's existing typecheck when the mode creates types or user-owned TypeScript changed.
|
||||||
|
6. Run the smallest application command affected by the change: `dev`, build, or a project-specific check.
|
||||||
|
|
||||||
|
Do not run a full production build solely to verify a new icon name. It is required when the bundler target, router, Webpack loader, asset URL, or deployment path changed, or when diagnosing a production-only error.
|
||||||
|
|
||||||
|
Perform visual, Network, and accessibility-tree checks only when a running application and browser tools are available. If those tools are unavailable, do not claim that colors, themes, accessibility, or the asset's HTTP response were verified; explicitly state what remains unchecked.
|
||||||
|
|
||||||
|
Use the Viewer for complex colors, transforms, and broad visual checks. Do not add a debug route for routine generation of one sprite.
|
||||||
|
|
||||||
|
## Diagnostics
|
||||||
|
|
||||||
|
Match the symptom to the relevant check and fix the root cause:
|
||||||
|
|
||||||
|
| Symptom | Likely cause | Action |
|
||||||
|
|---|---|---|
|
||||||
|
| `Missing sprite config file or module directory` | The positional path is missing | Pass one config file or a directory for config-less generation. |
|
||||||
|
| `Expected one config file or module directory` | Multiple paths were passed | Create one command per sprite and combine the scripts. |
|
||||||
|
| `Sprite mode is required` | Mode is absent from both config and CLI | Add `mode` to the object or pass the full `--mode`. |
|
||||||
|
| `Unsupported sprite config extension` | The supplied file is not `.ts`, `.js`, or `.json` | Use a supported config format. |
|
||||||
|
| A positive input source has no SVG matches | A folder is missing or empty, a glob matches nothing, or an exact path is missing or not an SVG | Resolve the source from the config directory and correct `input`; every positive item must produce at least one SVG. |
|
||||||
|
| Icons from a subdirectory are missing | A folder source was expected to scan recursively | Use an explicit glob such as `./icons/**/*.svg`; folders are shallow. |
|
||||||
|
| An excluded icon is still present | The exclusion lacks a leading `!`, is not in the `input` array, or is relative to the wrong directory | Add a matching `!` item and resolve it from the config directory. |
|
||||||
|
| CLI source selection is incomplete | Multiple sources were packed into one `--input` value or an option was omitted | Repeat `--input <path-or-glob>` once per source or exclusion. |
|
||||||
|
| Icon name or SVG ID collision | Two different files have the same basename, or a hash ID collides with a name | Rename one source SVG; do not select a file implicitly. |
|
||||||
|
| `Refusing to overwrite a user file` | A user-owned `.gitignore` already exists at the sprite-module root where the mode must create one | Do not overwrite it: choose another sprite directory or coordinate moving the existing `.gitignore`. |
|
||||||
|
| Missing `.svg-sprite/index.js` or name absent from autocomplete | This is expected for bare `standalone`; in other modes generation did not run, the barrel is wrong, or the type server cached an old module | Confirm the exact mode, run the sprite command, check `export * from './.svg-sprite/index.js'`, then typecheck; restart the TypeScript server if necessary. |
|
||||||
|
| SVG does not load or the URL is wrong | Mode and bundler differ, Webpack `publicPath` is wrong, or a custom loader intercepted the asset | Align mode with the build command, check Asset Modules/`publicPath`, and exclude the generated SVG from the incompatible loader. |
|
||||||
|
| Next build differs between SSR and browser | The module targets another bundler/router, or the URL was rewritten manually | Restore the generated `new URL(...)`, select the exact Next mode, and regenerate. |
|
||||||
|
| `color` does not change a multicolor icon | The icon uses several variables or is rendered through `<img>`/CSS background | Use `<FileManagerIcon>`/`<svg><use>` and the required `--icon-color-N` properties. |
|
||||||
|
| Gradient/filter renders incorrectly | Automatic color replacement cannot guarantee complex paint servers | Inspect the generated SVG; disable `replaceColors` for the sprite or simplify the source if necessary. |
|
||||||
|
| Viewer is empty | The manifest was not generated, the loader is not discoverable by the bundler, or the Client Component boundary is wrong | Generate the sprite first, then compare the manifest import and setup with the exact guide; in the App Router keep `'use client'` only in the Viewer component. |
|
||||||
|
| Remote manifest is rejected | It is not a `standalone@server` schema, contains an unsafe profile path, or its metadata is inconsistent | Publish the untouched complete server release and point `input` to its JSON manifest. |
|
||||||
|
| Remote sprite integrity check fails | The SVG is stale, truncated, or was changed independently from the manifest | Republish the manifest and both content-addressed profiles atomically; never overwrite a hashed SVG with different bytes. |
|
||||||
|
|
||||||
|
For an unknown error, record the complete CLI command, mode, config-file or directory path, and first stack/error message. Then reduce it to one sprite without deleting user files or a managed `.gitignore`.
|
||||||
|
|
||||||
|
## Operational reference map
|
||||||
|
|
||||||
|
References are included in the built skill. Open only the documents relevant to the current task, but always open the exact-mode guide before changing an integration.
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
- [Package README](./references/README.md) covers capabilities, the primary React/Next.js example, all supported families, and documentation links.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- [Configuration](./references/docs/en/configuration.md) covers JSON, JavaScript, and TypeScript configs, config fields, `input`, and CLI invocation.
|
||||||
|
|
||||||
|
### Exact-mode guides
|
||||||
|
|
||||||
|
- [`standalone`](./references/docs/en/guides/standalone.md) covers static HTML and custom SVG publishing.
|
||||||
|
- [`standalone@vite`](./references/docs/en/guides/standalone-vite.md) covers a vanilla Vite application and the Web Component.
|
||||||
|
- [`standalone@webpack`](./references/docs/en/guides/standalone-webpack.md) covers a vanilla Webpack 5 application and the Web Component.
|
||||||
|
- [`standalone@server`](./references/docs/en/guides/standalone-server.md) covers centralized content-addressed releases and remote consumers.
|
||||||
|
- [`react@vite`](./references/docs/en/guides/react-vite.md) covers React with Vite.
|
||||||
|
- [`react@webpack`](./references/docs/en/guides/react-webpack.md) covers React with Webpack 5.
|
||||||
|
- [`vue@vite`](./references/docs/en/guides/vue-vite.md) covers Vue with Vite.
|
||||||
|
- [`vue@webpack`](./references/docs/en/guides/vue-webpack.md) covers Vue with Webpack.
|
||||||
|
- [`nuxt@vite`](./references/docs/en/guides/nuxt-vite.md) covers Nuxt with Vite.
|
||||||
|
- [`nuxt@webpack`](./references/docs/en/guides/nuxt-webpack.md) covers Nuxt with Webpack.
|
||||||
|
- [`svelte@vite`](./references/docs/en/guides/svelte-vite.md) covers Svelte with Vite.
|
||||||
|
- [`svelte@webpack`](./references/docs/en/guides/svelte-webpack.md) covers Svelte with Webpack.
|
||||||
|
- [`sveltekit@vite`](./references/docs/en/guides/sveltekit-vite.md) covers SvelteKit with Vite.
|
||||||
|
- [`angular@application`](./references/docs/en/guides/angular-application.md) covers the Angular application builder.
|
||||||
|
- [`angular@webpack`](./references/docs/en/guides/angular-webpack.md) covers Angular with Webpack.
|
||||||
|
- [`astro@vite`](./references/docs/en/guides/astro-vite.md) covers Astro with Vite.
|
||||||
|
- [`solid@vite`](./references/docs/en/guides/solid-vite.md) covers Solid with Vite.
|
||||||
|
- [`solid@webpack`](./references/docs/en/guides/solid-webpack.md) covers Solid with Webpack.
|
||||||
|
- [`solid-start@vite`](./references/docs/en/guides/solid-start-vite.md) covers SolidStart with Vite.
|
||||||
|
- [`preact@vite`](./references/docs/en/guides/preact-vite.md) covers Preact with Vite.
|
||||||
|
- [`preact@webpack`](./references/docs/en/guides/preact-webpack.md) covers Preact with Webpack.
|
||||||
|
- [`qwik@vite`](./references/docs/en/guides/qwik-vite.md) covers Qwik with Vite.
|
||||||
|
- [`lit@vite`](./references/docs/en/guides/lit-vite.md) covers Lit with Vite.
|
||||||
|
- [`lit@webpack`](./references/docs/en/guides/lit-webpack.md) covers Lit with Webpack.
|
||||||
|
- [`alpine@vite`](./references/docs/en/guides/alpine-vite.md) covers Alpine.js with Vite.
|
||||||
|
- [`alpine@webpack`](./references/docs/en/guides/alpine-webpack.md) covers Alpine.js with Webpack.
|
||||||
|
- [`next@app/turbopack`](./references/docs/en/guides/next-app-turbopack.md) covers the Next.js App Router with Turbopack.
|
||||||
|
- [`next@app/webpack`](./references/docs/en/guides/next-app-webpack.md) covers the Next.js App Router with Webpack.
|
||||||
|
- [`next@pages/turbopack`](./references/docs/en/guides/next-pages-turbopack.md) covers the Next.js Pages Router with Turbopack.
|
||||||
|
- [`next@pages/webpack`](./references/docs/en/guides/next-pages-webpack.md) covers the Next.js Pages Router with Webpack.
|
||||||
|
|
||||||
|
### Technical references
|
||||||
|
|
||||||
|
- [Technical reference](./references/docs/en/reference/technical.md) covers requirements, CLI, unified configuration, naming, generated APIs, assets, transforms, colors, Viewer, Git, CI, and troubleshooting.
|
||||||
|
- [Programmatic API](./references/docs/en/reference/programmatic-api.md) covers `generateSprite`, overrides, config APIs, low-level compilation, and Viewer runtime.
|
||||||
|
|
||||||
|
### Agent-specific reference
|
||||||
|
|
||||||
|
- [Complex SVGs](./references/complex-svg.md) covers gradients, patterns, filters, masks, `url(#...)`, `viewBox`, fragment IDs, and visual diagnostics.
|
||||||
303
skills/svg-sprites/references/README.md
Normal file
303
skills/svg-sprites/references/README.md
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
# @gromlab/svg-sprites
|
||||||
|
|
||||||
|
🇬🇧 English | [🇷🇺 Русский](https://github.com/gromlab-ru/svg-sprites/blob/master/README_RU.md)
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` is a CLI tool for generating SVG sprites in modern web applications. It combines selected SVG icons into one or more external, cacheable sprites and prepares them for use in the UI.
|
||||||
|
|
||||||
|
Each exact mode generates a native typed component for its framework and bundler: Web Component, React, Vue, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit, or Alpine.js. In every case, the SVG remains a separate cacheable asset.
|
||||||
|
|
||||||
|
## An SVG sprite as simple as a regular SVG icon
|
||||||
|
|
||||||
|
One typed React component is generated for the entire sprite. Choose an icon with the `icon` prop, and your editor will autocomplete every available name.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" width={24} height={24} />
|
||||||
|
```
|
||||||
|
|
||||||
|
The component accepts familiar SVG attributes: dimensions, `color`, `className`, `style`, `aria-*`, and event handlers. If you need an outer container, add `wrapped`.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||||
|
```
|
||||||
|
|
||||||
|
You do not have to work with the sprite directly in your application. Use it like a regular SVG icon while benefiting from a single component, autocomplete, and TypeScript validation for every name.
|
||||||
|
|
||||||
|
## AI-friendly out of the box
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites` is designed to work with AI agents from the start. Add the ready-made skill and ask an agent to configure, migrate, or troubleshoot the package without lengthy instructions or manual documentation research.
|
||||||
|
|
||||||
|
Install the English skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the Russian skill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx skills add gromlab-ru/svg-sprites --skill svg-sprites-ru
|
||||||
|
```
|
||||||
|
|
||||||
|
## From SVG to component in three steps
|
||||||
|
|
||||||
|
The main example uses the Next.js App Router and Turbopack.
|
||||||
|
|
||||||
|
### 1. Specify the icons you need
|
||||||
|
|
||||||
|
Create directories for the source icons and the sprite:
|
||||||
|
|
||||||
|
```text
|
||||||
|
assets/
|
||||||
|
├── app-icons/
|
||||||
|
│ └── svg-sprite.config.json
|
||||||
|
└── svg-icons/
|
||||||
|
├── search.svg
|
||||||
|
└── settings.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the sprite configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` supports directory paths, individual SVG files, and glob patterns.
|
||||||
|
|
||||||
|
### 2. Add a generation script
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"prebuild": "npm run sprites"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create an entry point for the generated API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// assets/app-icons/index.ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
First run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
The package will generate `AppIcon`, TypeScript types, and a separate SVG sprite.
|
||||||
|
|
||||||
|
### 3. Use it like a regular icon
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function SearchButton() {
|
||||||
|
return (
|
||||||
|
<button type="button">
|
||||||
|
<AppIcon icon="search" width={20} height={20} />
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a Server Component. The icon does not require a provider, `'use client'`, or manual URL construction.
|
||||||
|
|
||||||
|
## Typed React component with autocomplete
|
||||||
|
|
||||||
|
Each sprite gets its own ready-to-use component. The `icon` prop is derived from the actual SVG names, so your editor shows the exact list of available icons and TypeScript catches typos immediately.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" /> // available icon
|
||||||
|
<AppIcon icon="serach" /> // TypeScript error
|
||||||
|
```
|
||||||
|
|
||||||
|
After you add a new SVG icon and run generation again, its name automatically appears in the types and autocomplete. There is no need to maintain components, union types, or a name registry manually.
|
||||||
|
|
||||||
|
## Next.js App Router and SSR out of the box
|
||||||
|
|
||||||
|
Generated components work in Server Components, SSR, and SSG without `'use client'`.
|
||||||
|
|
||||||
|
Using an icon does not turn the page into a Client Component, require a provider, or create an additional hydration boundary.
|
||||||
|
|
||||||
|
The same component can be used in `page.tsx`, `layout.tsx`, and both server and client components.
|
||||||
|
|
||||||
|
## Multiple sprites instead of one global sprite
|
||||||
|
|
||||||
|
Your project is not limited to a single icon set. Create independent sprites for shared elements, individual pages, and large UI modules.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" />
|
||||||
|
<AnalyticsIcon icon="chart" />
|
||||||
|
<EditorIcon icon="bold" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Each set gets its own typed component and SVG asset, so application sections do not load icons they do not need.
|
||||||
|
|
||||||
|
## Store each icon only once
|
||||||
|
|
||||||
|
Each SVG icon is stored once in the source library and can be included in any number of sprites. Shared icons do not need to be copied between pages and modules: a single source updates every set.
|
||||||
|
|
||||||
|
```text
|
||||||
|
search.svg ─┬─→ AppIcon
|
||||||
|
├─→ AnalyticsIcon
|
||||||
|
└─→ EditorIcon
|
||||||
|
```
|
||||||
|
|
||||||
|
Sprites are split for performance, while the source icon library remains unified.
|
||||||
|
|
||||||
|
## Browser caching
|
||||||
|
|
||||||
|
With a standard Vite, Webpack, or Next.js configuration, each sprite is emitted as a separate versioned SVG file.
|
||||||
|
|
||||||
|
As long as the icon set does not change, the browser can reuse its cached copy independently of JavaScript application updates.
|
||||||
|
|
||||||
|
Changes to React components do not require downloading the geometry of every icon again.
|
||||||
|
|
||||||
|
## JavaScript without SVG bloat
|
||||||
|
|
||||||
|
Icon paths remain in external SVG assets and do not add to application chunks.
|
||||||
|
|
||||||
|
```text
|
||||||
|
React code → JavaScript chunks
|
||||||
|
SVG icons → separate SVG assets
|
||||||
|
```
|
||||||
|
|
||||||
|
JavaScript handles the interface and behavior, while graphics are loaded and cached separately.
|
||||||
|
|
||||||
|
## Built-in SVG transformations
|
||||||
|
|
||||||
|
During generation, the package automatically prepares source SVG files for use in the UI:
|
||||||
|
|
||||||
|
- removes fixed `width` and `height` attributes;
|
||||||
|
- preserves the existing `viewBox`;
|
||||||
|
- converts `fill` and `stroke` values to CSS variables;
|
||||||
|
- adds smooth transitions directly to colored icon elements.
|
||||||
|
|
||||||
|
Each transformation can be configured or disabled independently.
|
||||||
|
|
||||||
|
## Control every color with CSS
|
||||||
|
|
||||||
|
During generation, `fill` and `stroke` colors are automatically converted to `--icon-color-N` CSS variables.
|
||||||
|
|
||||||
|
A monochrome icon inherits `currentColor`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" color="rebeccapurple" />
|
||||||
|
```
|
||||||
|
|
||||||
|
For a multicolor icon, each color can be changed independently:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="user"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#2563eb',
|
||||||
|
'--icon-color-2': '#dbeafe',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create themes, states, and hover effects without editing the SVG or making additional copies of the icon.
|
||||||
|
|
||||||
|
## SpriteViewer: every sprite on one debug page
|
||||||
|
|
||||||
|
`SpriteViewer` renders sprites from every supported exact mode in one place. One Web Component owns the visuals, while React also provides a thin bridge to it.
|
||||||
|
|
||||||
|
For each icon, you can see the generated CSS variables and their fallback colors. Change the values directly in the Viewer and see the result immediately.
|
||||||
|
|
||||||
|
It also provides ready-to-use examples for the manifest's framework, `<svg><use>`, `<img>`, and CSS.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The Viewer is added only to an internal debug page and does not become part of the generated icon components.
|
||||||
|
|
||||||
|
With bare standalone, the application loads the Viewer as a browser script and HTML element. Bundler and framework modes use the npm Web Component entry; React and Next.js may instead import the bridge from `@gromlab/svg-sprites/react`.
|
||||||
|
|
||||||
|
## 30 exact modes
|
||||||
|
|
||||||
|
The package supports 30 isolated exact modes: `standalone@server` for server-side generation of a universal SVG sprite and 29 consumer modes for modern frameworks and bundlers.
|
||||||
|
|
||||||
|
`standalone@server` lets you generate an SVG sprite ahead of time on a server or in CI/CD and publish it for shared use. The resulting sprite is not tied to a specific framework or bundler and works with every consumer mode.
|
||||||
|
|
||||||
|
The 29 consumer modes cover standalone, React, Next.js, Vue, Nuxt, Svelte, SvelteKit, Angular, Astro, Solid, SolidStart, Preact, Qwik, Lit, and Alpine.js across their supported Vite, Webpack, Turbopack, and application-builder variants.
|
||||||
|
|
||||||
|
All 29 consumer modes can work with sprites generated locally in the project or with universal sprites generated ahead of time on the server through `standalone@server`. The component API and the way icons are used in the application remain the same in both scenarios.
|
||||||
|
|
||||||
|
The integration matrix covers all 30 exact modes. A dedicated producer fixture verifies server-side generation of the universal sprite, while each of the 29 consumer applications generates and renders two independent sprites: one local and one remote.
|
||||||
|
|
||||||
|
All consumer applications pass a production build and Playwright tests, while typed modes are additionally checked by their framework-native toolchain. Every E2E test confirms that both local and remote sprites load and render, checks for browser errors, and verifies both groups in SpriteViewer.
|
||||||
|
|
||||||
|
## Clean Git history
|
||||||
|
|
||||||
|
Bundler and framework modes create a local `.gitignore` that excludes generated files and keeps them from cluttering project history, pull requests, and the codebase. Bare `standalone` leaves the repository policy to the application.
|
||||||
|
|
||||||
|
In bundler and framework modes, the repository contains the source SVG files, configuration, and `.gitignore` rule, while sprites, components, and types are regenerated locally and in CI through `prebuild`.
|
||||||
|
|
||||||
|
## Only icons in production
|
||||||
|
|
||||||
|
Generation can run entirely through `npx`, without adding the package to the project. Install it as a development dependency only when you need the Viewer, config types, or the programmatic API.
|
||||||
|
|
||||||
|
Production components use only local generated code, styles, and the external SVG file. The compiler and CLI are not bundled into the client application, while `SpriteViewer` is imported separately only where a debug page is needed.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
This README introduces the project's capabilities and demonstrates the primary use case. For setup, choose the guide for your stack.
|
||||||
|
|
||||||
|
### Server-side generation
|
||||||
|
|
||||||
|
- [Standalone + Server](docs/en/guides/standalone-server.md)
|
||||||
|
|
||||||
|
### Consumer quick starts
|
||||||
|
|
||||||
|
- [Bare standalone](docs/en/guides/standalone.md)
|
||||||
|
- [Standalone + Vite](docs/en/guides/standalone-vite.md)
|
||||||
|
- [Standalone + Webpack 5](docs/en/guides/standalone-webpack.md)
|
||||||
|
- [React + Vite](docs/en/guides/react-vite.md)
|
||||||
|
- [React + Webpack 5](docs/en/guides/react-webpack.md)
|
||||||
|
- [Vue + Vite](docs/en/guides/vue-vite.md)
|
||||||
|
- [Vue + Webpack](docs/en/guides/vue-webpack.md)
|
||||||
|
- [Nuxt + Vite](docs/en/guides/nuxt-vite.md)
|
||||||
|
- [Nuxt + Webpack](docs/en/guides/nuxt-webpack.md)
|
||||||
|
- [Svelte + Vite](docs/en/guides/svelte-vite.md)
|
||||||
|
- [Svelte + Webpack](docs/en/guides/svelte-webpack.md)
|
||||||
|
- [SvelteKit + Vite](docs/en/guides/sveltekit-vite.md)
|
||||||
|
- [Angular application builder](docs/en/guides/angular-application.md)
|
||||||
|
- [Angular + Webpack](docs/en/guides/angular-webpack.md)
|
||||||
|
- [Astro + Vite](docs/en/guides/astro-vite.md)
|
||||||
|
- [Solid + Vite](docs/en/guides/solid-vite.md)
|
||||||
|
- [Solid + Webpack](docs/en/guides/solid-webpack.md)
|
||||||
|
- [SolidStart + Vite](docs/en/guides/solid-start-vite.md)
|
||||||
|
- [Preact + Vite](docs/en/guides/preact-vite.md)
|
||||||
|
- [Preact + Webpack](docs/en/guides/preact-webpack.md)
|
||||||
|
- [Qwik + Vite](docs/en/guides/qwik-vite.md)
|
||||||
|
- [Lit + Vite](docs/en/guides/lit-vite.md)
|
||||||
|
- [Lit + Webpack](docs/en/guides/lit-webpack.md)
|
||||||
|
- [Alpine.js + Vite](docs/en/guides/alpine-vite.md)
|
||||||
|
- [Alpine.js + Webpack](docs/en/guides/alpine-webpack.md)
|
||||||
|
- [Next.js App Router + Turbopack](docs/en/guides/next-app-turbopack.md)
|
||||||
|
- [Next.js App Router + Webpack](docs/en/guides/next-app-webpack.md)
|
||||||
|
- [Next.js Pages Router + Turbopack](docs/en/guides/next-pages-turbopack.md)
|
||||||
|
- [Next.js Pages Router + Webpack](docs/en/guides/next-pages-webpack.md)
|
||||||
|
|
||||||
|
### Technical resources
|
||||||
|
|
||||||
|
- [Documentation index](docs/en/README.md)
|
||||||
|
- [Configuration](docs/en/configuration.md)
|
||||||
|
- [Technical reference](docs/en/reference/technical.md)
|
||||||
|
- [Programmatic API](docs/en/reference/programmatic-api.md)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
56
skills/svg-sprites/references/docs/en/README.md
Normal file
56
skills/svg-sprites/references/docs/en/README.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Documentation
|
||||||
|
|
||||||
|
Choose one exact mode guide for setup. The guides are standalone documents and
|
||||||
|
can also be used unchanged by AI skills.
|
||||||
|
|
||||||
|
The common format for JSON, JavaScript, and TypeScript config files is described in the [configuration guide](configuration.md).
|
||||||
|
|
||||||
|
## Consumer Quick Starts
|
||||||
|
|
||||||
|
| Project | Exact mode | Guide |
|
||||||
|
|---|---|---|
|
||||||
|
| Static HTML or custom publishing | `standalone` | [Bare standalone](guides/standalone.md) |
|
||||||
|
| Vanilla + Vite | `standalone@vite` | [Standalone + Vite](guides/standalone-vite.md) |
|
||||||
|
| Vanilla + Webpack 5 | `standalone@webpack` | [Standalone + Webpack](guides/standalone-webpack.md) |
|
||||||
|
| React + Vite | `react@vite` | [React + Vite](guides/react-vite.md) |
|
||||||
|
| React + Webpack 5 | `react@webpack` | [React + Webpack](guides/react-webpack.md) |
|
||||||
|
| Vue + Vite | `vue@vite` | [Vue + Vite](guides/vue-vite.md) |
|
||||||
|
| Vue + Webpack | `vue@webpack` | [Vue + Webpack](guides/vue-webpack.md) |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` | [Nuxt + Vite](guides/nuxt-vite.md) |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` | [Nuxt + Webpack](guides/nuxt-webpack.md) |
|
||||||
|
| Svelte + Vite | `svelte@vite` | [Svelte + Vite](guides/svelte-vite.md) |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` | [Svelte + Webpack](guides/svelte-webpack.md) |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` | [SvelteKit + Vite](guides/sveltekit-vite.md) |
|
||||||
|
| Angular application builder | `angular@application` | [Angular application builder](guides/angular-application.md) |
|
||||||
|
| Angular + Webpack | `angular@webpack` | [Angular + Webpack](guides/angular-webpack.md) |
|
||||||
|
| Astro + Vite | `astro@vite` | [Astro + Vite](guides/astro-vite.md) |
|
||||||
|
| Solid + Vite | `solid@vite` | [Solid + Vite](guides/solid-vite.md) |
|
||||||
|
| Solid + Webpack | `solid@webpack` | [Solid + Webpack](guides/solid-webpack.md) |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` | [SolidStart + Vite](guides/solid-start-vite.md) |
|
||||||
|
| Preact + Vite | `preact@vite` | [Preact + Vite](guides/preact-vite.md) |
|
||||||
|
| Preact + Webpack | `preact@webpack` | [Preact + Webpack](guides/preact-webpack.md) |
|
||||||
|
| Qwik + Vite | `qwik@vite` | [Qwik + Vite](guides/qwik-vite.md) |
|
||||||
|
| Lit + Vite | `lit@vite` | [Lit + Vite](guides/lit-vite.md) |
|
||||||
|
| Lit + Webpack | `lit@webpack` | [Lit + Webpack](guides/lit-webpack.md) |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` | [Alpine.js + Vite](guides/alpine-vite.md) |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` | [Alpine.js + Webpack](guides/alpine-webpack.md) |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` | [App Router + Turbopack](guides/next-app-turbopack.md) |
|
||||||
|
| Next.js App Router + Webpack | `next@app/webpack` | [App Router + Webpack](guides/next-app-webpack.md) |
|
||||||
|
| Next.js Pages Router + Turbopack | `next@pages/turbopack` | [Pages Router + Turbopack](guides/next-pages-turbopack.md) |
|
||||||
|
| Next.js Pages Router + Webpack | `next@pages/webpack` | [Pages Router + Webpack](guides/next-pages-webpack.md) |
|
||||||
|
|
||||||
|
Every consumer guide follows the same order:
|
||||||
|
|
||||||
|
1. Generate the sprite through `npx` without adding the package to the project.
|
||||||
|
2. Use the sprite in the application.
|
||||||
|
3. Optionally add the Viewer for debugging and previews.
|
||||||
|
|
||||||
|
## Server-Side Generation
|
||||||
|
|
||||||
|
Use [`standalone@server`](guides/standalone-server.md) to generate a universal SVG sprite on a server or in CI/CD for all consumer modes.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Configuration](configuration.md)
|
||||||
|
- [Technical reference](reference/technical.md)
|
||||||
|
- [Programmatic API](reference/programmatic-api.md)
|
||||||
139
skills/svg-sprites/references/docs/en/configuration.md
Normal file
139
skills/svg-sprites/references/docs/en/configuration.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# Configuration
|
||||||
|
|
||||||
|
Each config file describes one independent sprite. The CLI does not discover config files automatically, so always pass the path explicitly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSON
|
||||||
|
|
||||||
|
JSON works for most projects and does not require installing the package locally:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"description": "Shared application icons",
|
||||||
|
"input": [
|
||||||
|
"./icons",
|
||||||
|
"../../assets/icons/**/*.svg",
|
||||||
|
"!../../assets/icons/deprecated-*.svg"
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"removeSize": true,
|
||||||
|
"replaceColors": true,
|
||||||
|
"addTransition": true
|
||||||
|
},
|
||||||
|
"generatedNotice": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Default | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `mode` | None | Exact mode matching the framework and bundler |
|
||||||
|
| `source` | `local` | `local` for source SVG files or `remote` for a `standalone@server` manifest |
|
||||||
|
| `name` | Kebab-case module directory name; for `svg-sprite` and `svg-sprites`, the parent directory name | Sprite name; in modes with a component, it also determines the component and type names |
|
||||||
|
| `description` | None | Description used in types and the Viewer |
|
||||||
|
| `input` | `./icons` | Directory, SVG file, glob pattern, or array of sources |
|
||||||
|
| `transform` | All enabled | SVG preparation options |
|
||||||
|
| `generatedNotice` | `true` | Full or compact warning in generated files |
|
||||||
|
|
||||||
|
Paths and glob patterns in `input` are resolved relative to the config file's directory. A pattern prefixed with `!` excludes matches.
|
||||||
|
|
||||||
|
## Remotely built sprite
|
||||||
|
|
||||||
|
A consumer config for a server manifest only contains the mode, source, and input:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"source": "remote",
|
||||||
|
"input": "https://assets.example/releases/app/svg-sprite.manifest.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` accepts one HTTP(S) URL or local manifest path. The name, description,
|
||||||
|
transforms, and generated notice come from the manifest. The generator downloads
|
||||||
|
and verifies the matching SVG profile before the adapter creates its normal local
|
||||||
|
components, types, and bundler asset.
|
||||||
|
|
||||||
|
## Server build
|
||||||
|
|
||||||
|
`standalone@server` combines local paths/globs with HTTP(S) SVG descriptors:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
mode: 'standalone@server',
|
||||||
|
name: 'app',
|
||||||
|
input: [
|
||||||
|
'./icons/**/*.svg',
|
||||||
|
{
|
||||||
|
name: 'remote-logo',
|
||||||
|
url: 'https://assets.example/logo.svg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The mode creates two content-addressed SVG profiles and `svg-sprite.manifest.json`.
|
||||||
|
`sha256` is optional for HTTP inputs; when present, it must be the expected 64-character
|
||||||
|
hexadecimal SHA-256 digest and the build verifies the received bytes.
|
||||||
|
|
||||||
|
## JavaScript
|
||||||
|
|
||||||
|
A JavaScript config default-exports a plain object:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'icons',
|
||||||
|
input: './icons',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Pass the path to the `.js` file to the CLI just like a JSON file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## TypeScript
|
||||||
|
|
||||||
|
To type-check a TypeScript config, install the package as a development dependency:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `defineSpriteConfig`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'icons',
|
||||||
|
input: './icons',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, use `satisfies` with a type-only import:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { SpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'icons',
|
||||||
|
input: './icons',
|
||||||
|
} satisfies SpriteConfig
|
||||||
|
```
|
||||||
|
|
||||||
|
The CLI loads `.ts` config files directly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
For the complete list of modes, CLI flags, naming rules, and transform options, see the [technical reference](reference/technical.md).
|
||||||
91
skills/svg-sprites/references/docs/en/guides/alpine-vite.md
Normal file
91
skills/svg-sprites/references/docs/en/guides/alpine-vite.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# SVG Sprite for Alpine.js with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an Alpine.js application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "alpine@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator does not need to be added to the application dependencies: run it through `npx`.
|
||||||
|
|
||||||
|
Add generation before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Alpine plugin `appAlpinePlugin`, the `x-app-icon` directive, and the `$appIconHref` magic.
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the generated plugin before starting Alpine:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
import { appAlpinePlugin } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
Alpine.plugin(appAlpinePlugin)
|
||||||
|
Alpine.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the reactive directive on an SVG element:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
x-data="{ iconName: 'icon-name' }"
|
||||||
|
x-app-icon="iconName"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
The directive expression resolves to a source SVG file name without the extension. A monochrome icon inherits `color`; override multicolor icon layers with `--icon-color-N`. Vite loads the generated CSS and emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page and is only needed during development. Install it separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `src/svg-sprite-debug.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open the development page. Viewer is independent from the Alpine plugin.
|
||||||
103
skills/svg-sprites/references/docs/en/guides/alpine-webpack.md
Normal file
103
skills/svg-sprites/references/docs/en/guides/alpine-webpack.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# SVG Sprite for Alpine.js with Webpack 5
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an Alpine.js application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "alpine@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator does not need to be added to the application dependencies: run it through `npx`.
|
||||||
|
|
||||||
|
Add generation before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Alpine plugin `appAlpinePlugin`, the `x-app-icon` directive, and the `$appIconHref` magic.
|
||||||
|
|
||||||
|
Generated Alpine CSS is imported with the `?inline` query. Add an Asset Module rule to `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
resourceQuery: /inline/,
|
||||||
|
type: 'asset/source',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the generated plugin before starting Alpine:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
import { appAlpinePlugin } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
Alpine.plugin(appAlpinePlugin)
|
||||||
|
Alpine.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the reactive directive on an SVG element:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
x-data="{ iconName: 'icon-name' }"
|
||||||
|
x-app-icon="iconName"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
The directive expression resolves to a source SVG file name without the extension. A monochrome icon inherits `color`; override multicolor icon layers with `--icon-color-N`. Webpack 5 emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page and is only needed during development. Install it separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.viewerTitle = 'Project icons'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Include this entry only in development. Viewer is independent from the Alpine plugin.
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# SVG Sprite for Angular with the Application Builder
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an Angular application built with `@angular/build:application`.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "angular@application",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Run generation through `npx` before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"prestart": "npm run sprites",
|
||||||
|
"start": "ng serve",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "ng build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The application builder emits imported SVG files when its file loader is enabled. Add this option to the build target in `angular.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"builder": "@angular/build:application",
|
||||||
|
"options": {
|
||||||
|
"loader": { ".svg": "file" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index'
|
||||||
|
```
|
||||||
|
|
||||||
|
Import the generated standalone component. The value `name: "app"` creates `AppIcon` and the selector `app-icon`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [AppIcon],
|
||||||
|
template: `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width: 24px; height: 24px; color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class AppComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` input is typed from source file names. Monochrome icons inherit `color`; use `--icon-color-N` for individual colors.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is optional and only needed during development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Import `@gromlab/svg-sprites/viewer/element`, add `CUSTOM_ELEMENTS_SCHEMA`, and place `<gromlab-sprite-viewer [sources]="viewerSources" />` in the template. Load the generated manifest while omitting framework-only usage metadata:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
readonly viewerSources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
The Viewer uses the same production sprite URL as `AppIcon`.
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# SVG Sprite for Angular with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an Angular application built by the Webpack-based Angular CLI browser builder.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "angular@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This mode is for a workspace whose build target uses the official Webpack builder:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"builder": "@angular-devkit/build-angular:browser"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Generate the sprite through `npx` before each start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"prestart": "npm run sprites",
|
||||||
|
"start": "ng serve",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "ng build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack resolves the generated `new URL(..., import.meta.url)` expression and emits `sprite.svg` as a production asset.
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index'
|
||||||
|
```
|
||||||
|
|
||||||
|
Import the generated standalone component. The value `name: "app"` creates `AppIcon` and the selector `app-icon`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [AppIcon],
|
||||||
|
template: `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width: 24px; height: 24px; color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class AppComponent {}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` input is typed from source file names. Monochrome icons inherit `color`; use `--icon-color-N` for individual colors.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is optional and only needed during development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Import `@gromlab/svg-sprites/viewer/element`, add `CUSTOM_ELEMENTS_SCHEMA`, and place `<gromlab-sprite-viewer [sources]="viewerSources" />` in the template:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
readonly viewerSources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
The Viewer and `AppIcon` share the Webpack-emitted sprite URL.
|
||||||
92
skills/svg-sprites/references/docs/en/guides/astro-vite.md
Normal file
92
skills/svg-sprites/references/docs/en/guides/astro-vite.md
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# SVG Sprite for Astro with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an Astro application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "astro@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Generate the sprite through `npx` before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "astro dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "astro check && astro build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.d.ts` for the same typed API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
The value `name: "app"` creates the native Astro component `AppIcon`. Use it in a page:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
---
|
||||||
|
import { AppIcon } from '../../assets/app-icons/index.js'
|
||||||
|
---
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop is typed from source file names. Vite emits `sprite.svg` from the component's static asset import.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is optional and only needed during development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the Viewer to the page and connect the generated manifest in a client script:
|
||||||
|
|
||||||
|
```astro
|
||||||
|
<gromlab-sprite-viewer id="sprite-viewer"></gromlab-sprite-viewer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('#sprite-viewer')!
|
||||||
|
viewer.sources = [async () => {
|
||||||
|
const { default: manifest } = await import(
|
||||||
|
'../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
)
|
||||||
|
const { usage: _usage, ...viewerManifest } = manifest
|
||||||
|
return viewerManifest
|
||||||
|
}]
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
The manifest retains Astro usage metadata while Viewer renders the same production sprite.
|
||||||
86
skills/svg-sprites/references/docs/en/guides/lit-vite.md
Normal file
86
skills/svg-sprites/references/docs/en/guides/lit-vite.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# SVG Sprite for Lit with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Lit application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "lit@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator does not need to be added to the application dependencies: run it through `npx`.
|
||||||
|
|
||||||
|
Add generation before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Lit class `AppIcon`, the `<app-icon>` tag, and the `defineAppIcon` registration function.
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the component before rendering it:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineAppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
defineAppIcon()
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></app-icon>
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` property accepts source SVG file names without the extension. A monochrome icon inherits `color`; override multicolor icon layers with `--icon-color-N`. Vite loads the component CSS and emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page and is only needed during development. Install it separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `src/svg-sprite-debug.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open the development page. Viewer is not required by `AppIcon`.
|
||||||
98
skills/svg-sprites/references/docs/en/guides/lit-webpack.md
Normal file
98
skills/svg-sprites/references/docs/en/guides/lit-webpack.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG Sprite for Lit with Webpack 5
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Lit application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "lit@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The generator does not need to be added to the application dependencies: run it through `npx`.
|
||||||
|
|
||||||
|
Add generation before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Lit class `AppIcon`, the `<app-icon>` tag, and the `defineAppIcon` registration function.
|
||||||
|
|
||||||
|
Generated Lit CSS is imported with the `?inline` query. Add an Asset Module rule to `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
resourceQuery: /inline/,
|
||||||
|
type: 'asset/source',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the component before rendering it:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineAppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
defineAppIcon()
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<app-icon
|
||||||
|
icon="icon-name"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="width:24px;height:24px;color:#334155;--icon-color-2:#f59e0b"
|
||||||
|
></app-icon>
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` property accepts source SVG file names without the extension. A monochrome icon inherits `color`; override multicolor icon layers with `--icon-color-N`. Webpack 5 emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page and is only needed during development. Install it separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.viewerTitle = 'Project icons'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Include this entry only in development. Viewer is not required by `AppIcon`.
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# SVG Sprite for Next.js App Router with Turbopack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Next.js application using App Router and Turbopack.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in a Server Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` does not need `'use client'`. Turbopack automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function SvgSpriteViewer() {
|
||||||
|
return <SpriteViewer sources={sources} title="Project icons" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the route `app/svg-sprite/page.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
|
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
if (process.env.NODE_ENV !== 'development') notFound()
|
||||||
|
|
||||||
|
return <SvgSpriteViewer />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404.
|
||||||
108
skills/svg-sprites/references/docs/en/guides/next-app-webpack.md
Normal file
108
skills/svg-sprites/references/docs/en/guides/next-app-webpack.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# SVG Sprite for Next.js App Router with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Next.js application using App Router and Webpack.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@app/webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in a Server Component:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` does not need `'use client'`. Next.js automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the Client Component `app/svg-sprite/SvgSpriteViewer.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export function SvgSpriteViewer() {
|
||||||
|
return <SpriteViewer sources={sources} title="Project icons" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the route `app/svg-sprite/page.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
|
import { SvgSpriteViewer } from './SvgSpriteViewer'
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
if (process.env.NODE_ENV !== 'development') notFound()
|
||||||
|
|
||||||
|
return <SvgSpriteViewer />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG Sprite for Next.js Pages Router with Turbopack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Next.js application using Pages Router and Turbopack.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@pages/turbopack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component on a page:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// pages/index.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The component works with SSR, SSG, and client-side navigation. Turbopack automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the page `pages/svg-sprite.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import type { GetStaticProps } from 'next'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
return <SpriteViewer sources={sources} title="Project icons" />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = () =>
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
? { props: {} }
|
||||||
|
: { notFound: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# SVG Sprite for Next.js Pages Router with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Next.js application using Pages Router and Webpack.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "next@pages/webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component on a page:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// pages/index.tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The component works with SSR, SSG, and client-side navigation. Next.js automatically adds `sprite.svg` to the production build, so you do not need to move it to `public`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the page `pages/svg-sprite.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import type { GetStaticProps } from 'next'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export default function SvgSpritePage() {
|
||||||
|
return <SpriteViewer sources={sources} title="Project icons" />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = () =>
|
||||||
|
process.env.NODE_ENV === 'development'
|
||||||
|
? { props: {} }
|
||||||
|
: { notFound: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite`. In production, the route returns 404.
|
||||||
100
skills/svg-sprites/references/docs/en/guides/nuxt-vite.md
Normal file
100
skills/svg-sprites/references/docs/en/guides/nuxt-vite.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# SVG Sprite for Nuxt with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Nuxt application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "nuxt@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "nuxt build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Vue component `AppIcon`. Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in a Nuxt page or layout:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` is SSR-safe and does not need a client-only wrapper. Vite emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `app/components/SvgSpriteViewer.client.vue` so the browser-only Viewer is not evaluated during SSR:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer :sources="sources" viewer-title="Project icons" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Mark `gromlab-sprite-viewer` as a custom element in `nuxt.config.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
vue: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Render `<SvgSpriteViewer />` on your development page. Viewer is isolated from the generated `AppIcon` runtime.
|
||||||
113
skills/svg-sprites/references/docs/en/guides/nuxt-webpack.md
Normal file
113
skills/svg-sprites/references/docs/en/guides/nuxt-webpack.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# SVG Sprite for Nuxt with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Nuxt application built with Webpack.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "nuxt@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Use the Nuxt Webpack builder in `nuxt.config.ts`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @nuxt/webpack-builder
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
builder: '@nuxt/webpack-builder',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Add generation commands to `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "nuxt build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Vue component `AppIcon`. Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in a Nuxt page or layout:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
`AppIcon` is SSR-safe and does not need a client-only wrapper. Webpack emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `app/components/SvgSpriteViewer.client.vue` so the browser-only Viewer is not evaluated during SSR:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer :sources="sources" viewer-title="Project icons" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend the existing `nuxt.config.ts` settings so Vue treats the Viewer as a custom element:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
builder: '@nuxt/webpack-builder',
|
||||||
|
vue: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Render `<SvgSpriteViewer />` on your development page. Viewer is isolated from the generated `AppIcon` runtime.
|
||||||
75
skills/svg-sprites/references/docs/en/guides/preact-vite.md
Normal file
75
skills/svg-sprites/references/docs/en/guides/preact-vite.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG Sprite for Preact with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Preact application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "preact@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Run it through `npx` before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js` and `assets/app-icons/index.d.ts` with the same export:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the generated plain-JavaScript Preact component:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Vite automatically emits the imported `sprite.svg` as a production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Install Viewer only for development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Mount it from a debug entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG Sprite for Preact with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Preact application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "preact@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Run it through `npx` before Webpack starts or builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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": "tsc --noEmit && webpack --mode production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js` and `assets/app-icons/index.d.ts` with the same export:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the generated Preact component:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack Asset Modules emit `sprite.svg` from the generated `new URL(...)` expression.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Install Viewer only for development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Mount it from a development-only entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
82
skills/svg-sprites/references/docs/en/guides/qwik-vite.md
Normal file
82
skills/svg-sprites/references/docs/en/guides/qwik-vite.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# SVG Sprite for Qwik with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an SSR Qwik application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "qwik@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Regenerate through `npx` before Vite starts or builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite --mode ssr",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "tsc --noEmit && vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated component is a Qwik `component$` and is safe during SSR:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { component$ } from '@builder.io/qwik'
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default component$(() => (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
```
|
||||||
|
|
||||||
|
The component uses a static Vite asset import and does not access browser globals during SSR.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is browser-only, optional development tooling:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Load it from a visible task:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export const IconViewer = component$(() => {
|
||||||
|
const host = useSignal<HTMLElement>()
|
||||||
|
useVisibleTask$(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.value?.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
})
|
||||||
|
```
|
||||||
115
skills/svg-sprites/references/docs/en/guides/react-vite.md
Normal file
115
skills/svg-sprites/references/docs/en/guides/react-vite.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# SVG Sprite for React with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a React application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite automatically includes the component styles and adds `sprite.svg` to the production build.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `svg-sprite.html` in the project root:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Project icons</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- React root for debugging and previewing the SVG sprite in Viewer -->
|
||||||
|
<div id="svg-sprite-viewer"></div>
|
||||||
|
|
||||||
|
<!-- Load the debug script created below -->
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `src/svg-sprite-debug.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
createRoot(document.getElementById('svg-sprite-viewer')!).render(
|
||||||
|
<SpriteViewer sources={sources} title="Project icons" />,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite.html`.
|
||||||
|
|
||||||
|
The standard Vite production build uses only `index.html` and does not include the Viewer page.
|
||||||
132
skills/svg-sprites/references/docs/en/guides/react-webpack.md
Normal file
132
skills/svg-sprites/references/docs/en/guides/react-webpack.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# SVG Sprite for React with Webpack 5
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a React application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the React component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style={{
|
||||||
|
color: '#334155',
|
||||||
|
'--icon-color-2': '#f59e0b',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`.
|
||||||
|
|
||||||
|
The component uses CSS Modules. If the project does not process them yet, install the loaders:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev style-loader css-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add a rule with a default export to `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.module\.css$/i,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: { modules: { namedExport: false } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 automatically adds `sprite.svg` to the production build.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development.
|
||||||
|
|
||||||
|
Install Viewer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the entry `src/svg-sprite-debug.tsx`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const container = document.createElement('div')
|
||||||
|
document.body.append(container)
|
||||||
|
|
||||||
|
createRoot(container).render(
|
||||||
|
<SpriteViewer sources={sources} title="Project icons" />,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the script to the main entry only in development mode. Keep the rest of your `webpack.config.js` settings:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default (_env, argv) => ({
|
||||||
|
// Other Webpack settings.
|
||||||
|
entry: [
|
||||||
|
'./src/main.tsx',
|
||||||
|
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.tsx'] : []),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev`. Viewer appears on the application's main page and is not included in the production build.
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG Sprite for SolidStart with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in an SSR SolidStart application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid-start@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Regenerate through `npx` before Vinxi starts or builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vinxi dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vinxi build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated component is safe to render on the server:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The component uses a static Vite asset import and does not access browser globals during SSR.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is browser-only, optional development tooling:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Load it from `onMount` so it is excluded from server rendering:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { onMount } from 'solid-js'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export function IconViewer() {
|
||||||
|
let host!: HTMLDivElement
|
||||||
|
onMount(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
}
|
||||||
|
```
|
||||||
83
skills/svg-sprites/references/docs/en/guides/solid-vite.md
Normal file
83
skills/svg-sprites/references/docs/en/guides/solid-vite.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG Sprite for Solid with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Solid application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Run it through `npx` and regenerate before development and production builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
The name `app` creates the Solid component `AppIcon`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Vite emits `sprite.svg` as a production asset. Monochrome icons inherit `color`; multicolor icons use `--icon-color-N`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer is optional and only needed during development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Mount it from a debug component after the browser is ready:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { onMount } from 'solid-js'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
export function IconViewer() {
|
||||||
|
let host!: HTMLDivElement
|
||||||
|
onMount(async () => {
|
||||||
|
await import('@gromlab/svg-sprites/viewer/element')
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
host.append(viewer)
|
||||||
|
})
|
||||||
|
return <div ref={host} />
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# SVG Sprite for Solid with Webpack
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Solid application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "solid@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency. Run it through `npx` before Webpack starts or builds:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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": "tsc --noEmit && webpack --mode production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js` and `assets/app-icons/index.d.ts` with the same export:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the generated Solid component:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
|
||||||
|
export function SaveIcon() {
|
||||||
|
return (
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
aria-label="Done"
|
||||||
|
style={{ color: '#334155', '--icon-color-2': '#f59e0b' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack Asset Modules emit `sprite.svg` from the generated `new URL(...)`. Keep `.jsx` processing enabled for the generated Solid component.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Install Viewer only for development:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add it to a development-only entry:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer')
|
||||||
|
viewer.sources = [() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js')]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Universal SVG Sprite Generated on a Server
|
||||||
|
|
||||||
|
Generate a universal SVG sprite in CI or a server worker for applications that use different frameworks and bundlers.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
You do not need to install the package in the worker.
|
||||||
|
|
||||||
|
### 1. Prepare the workspace
|
||||||
|
|
||||||
|
Place the source SVGs in the current workspace's `icons` directory:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
└── icons/
|
||||||
|
├── search.svg
|
||||||
|
└── settings.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
Each filename without the extension becomes an icon name.
|
||||||
|
|
||||||
|
### 2. Run generation
|
||||||
|
|
||||||
|
Pass the mode, sprite name, and SVG path through the CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites \
|
||||||
|
--mode standalone@server \
|
||||||
|
--name app \
|
||||||
|
--input './icons/**/*.svg' \
|
||||||
|
.
|
||||||
|
```
|
||||||
|
|
||||||
|
This worker workflow does not need a config file. The result appears in `./.svg-sprite`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── icons/
|
||||||
|
│ ├── search.svg
|
||||||
|
│ └── settings.svg
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Publish the result
|
||||||
|
|
||||||
|
Upload the contents of `.svg-sprite` to a dedicated S3 bucket directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
aws s3 sync ./.svg-sprite/ s3://my-bucket/app-icons/
|
||||||
|
```
|
||||||
|
|
||||||
|
The same directory can be served through a CDN. The public URL does not contain a `.svg-sprite` segment:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://cdn.example.com/app-icons/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also run `standalone@server` through a JSON, JavaScript, or TypeScript config. A config is useful for persistent settings, local SVGs from several directories, and SVGs loaded over HTTP(S).
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
Create a regular config in the consumer application. For example, with React and Vite:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/app-icons/
|
||||||
|
├── index.ts
|
||||||
|
└── svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the consumer mode and the CDN manifest URL:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "react@vite",
|
||||||
|
"source": "remote",
|
||||||
|
"input": "https://cdn.example.com/app-icons/svg-sprite.manifest.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a user-owned entry point:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/app-icons/index.ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Run normal generation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites src/app-icons/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use the generated component exactly as with a sprite built from local SVGs:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppIcon } from './app-icons'
|
||||||
|
|
||||||
|
export function SearchButton() {
|
||||||
|
return <AppIcon icon="search" aria-label="Search" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The same CDN manifest works with all 29 consumer modes. Each one preserves the native API of its selected framework and bundler.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
`standalone@server` does not create a separate icon preview page. Connect the published sprite to a consumer application and open it in SpriteViewer: the remote set appears in the same way as a local one.
|
||||||
114
skills/svg-sprites/references/docs/en/guides/standalone-vite.md
Normal file
114
skills/svg-sprites/references/docs/en/guides/standalone-vite.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# SVG Sprite for Vite Without a Framework
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Vite application without a framework.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the `<app-icon>` element.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the element in `src/main.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '../assets/app-icons'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the icon in HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="icon-name" role="img" aria-label="Done"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` value is the source SVG filename without the extension. Set its size and colors with CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
app-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #334155;
|
||||||
|
--icon-color-2: #f59e0b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. Viewer shows the variables you need.
|
||||||
|
|
||||||
|
Vite automatically adds `sprite.svg` to the production build. You do not need to copy it to `public`.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `svg-sprite.html` in the project root:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Project icons</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Viewer component for debugging and previewing the SVG sprite -->
|
||||||
|
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||||
|
|
||||||
|
<!-- Load the debug script created below -->
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `src/svg-sprite-debug.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite.html`.
|
||||||
|
|
||||||
|
Viewer is not required for `<app-icon>` and is not imported by the application's main code.
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# SVG Sprite for Webpack 5 Without a Framework
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Webpack 5 application without a framework.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the `<app-icon>` element.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Register the element in the application's main entry:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '../assets/app-icons'
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the icon in HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="icon-name" role="img" aria-label="Done"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` value is the source SVG filename without the extension. Set its size and colors with CSS:
|
||||||
|
|
||||||
|
```css
|
||||||
|
app-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #334155;
|
||||||
|
--icon-color-2: #f59e0b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`. Viewer shows the variables you need.
|
||||||
|
|
||||||
|
Webpack 5 automatically adds `sprite.svg` to the production build.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development.
|
||||||
|
|
||||||
|
Install Viewer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the entry `src/svg-sprite-debug.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.createElement('gromlab-sprite-viewer') as SpriteViewerElement
|
||||||
|
viewer.viewerTitle = 'Project icons'
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
document.body.append(viewer)
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the script to the main entry only in development mode. Keep the rest of your `webpack.config.js` settings:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default (_env, argv) => ({
|
||||||
|
// Other Webpack settings.
|
||||||
|
entry: [
|
||||||
|
'./src/main.ts',
|
||||||
|
...(argv.mode === 'development' ? ['./src/svg-sprite-debug.ts'] : []),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev`. Viewer appears on the application's main page.
|
||||||
|
|
||||||
|
Viewer is only added to the development build and is not included in production.
|
||||||
83
skills/svg-sprites/references/docs/en/guides/standalone.md
Normal file
83
skills/svg-sprites/references/docs/en/guides/standalone.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# SVG Sprite for a Site Without a Bundler
|
||||||
|
|
||||||
|
Combine SVG icons into one file and use them on an HTML page.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
You do not need to install the package in your project.
|
||||||
|
|
||||||
|
### 1. Create the sprite config
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "standalone",
|
||||||
|
"name": "icons",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Generate the sprite
|
||||||
|
|
||||||
|
Pass the config path to the command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The package collects the icons in a `.svg-sprite` directory next to the config:
|
||||||
|
|
||||||
|
```text
|
||||||
|
assets/app-icons/.svg-sprite/
|
||||||
|
├── sprite.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
- `sprite.svg` is the finished sprite for use on the site.
|
||||||
|
- `svg-sprite.manifest.json` contains icon data for Viewer.
|
||||||
|
|
||||||
|
The `.svg-sprite` directory is created automatically and fully replaced on every generation. Do not edit its contents manually.
|
||||||
|
|
||||||
|
### 3. Use an icon
|
||||||
|
|
||||||
|
In `index.html`, point to the generated `sprite.svg`. After `#`, add the icon file name without the `.svg` extension:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
aria-label="Done"
|
||||||
|
>
|
||||||
|
<use href="./assets/app-icons/.svg-sprite/sprite.svg#icon-name"></use>
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
`sprite.svg` is a technical file, not an icon gallery. Opening it does not provide a convenient view of the whole set. Gradients, masks, filters, and references to internal `id` values may also render with artifacts.
|
||||||
|
|
||||||
|
Use the official Viewer for visual checks. It displays every icon in the sprite and helps you verify its colors and rendering.
|
||||||
|
|
||||||
|
Viewer is optional and intended only for development. You do not need to install the package through npm.
|
||||||
|
|
||||||
|
Viewer works directly with files from `.svg-sprite`. Nothing needs to be copied.
|
||||||
|
|
||||||
|
### Add Viewer to the page
|
||||||
|
|
||||||
|
Add a module script to `index.html` and provide paths to the generated manifest and sprite:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="https://cdn.jsdelivr.net/npm/@gromlab/svg-sprites/dist/viewer-element.js"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
viewer-title="Project icons"
|
||||||
|
manifest-url="./assets/app-icons/.svg-sprite/svg-sprite.manifest.json"
|
||||||
|
sprite-url="./assets/app-icons/.svg-sprite/sprite.svg"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can move Viewer to a separate HTML file in the site root used only for development and icon checks.
|
||||||
95
skills/svg-sprites/references/docs/en/guides/svelte-vite.md
Normal file
95
skills/svg-sprites/references/docs/en/guides/svelte-vite.md
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# SVG Sprite for Svelte with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Svelte application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "svelte@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Svelte component `AppIcon`.
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite automatically includes the component styles and emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development-only Svelte page or component:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
node.sources = sources
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
use:connectViewer
|
||||||
|
viewer-title="Project icons"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open the page containing Viewer. Do not import this development component from the production entry.
|
||||||
105
skills/svg-sprites/references/docs/en/guides/svelte-webpack.md
Normal file
105
skills/svg-sprites/references/docs/en/guides/svelte-webpack.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# SVG Sprite for Svelte with Webpack 5
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Svelte application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "svelte@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Svelte component `AppIcon`.
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated component is a native `.svelte` file. The normal `svelte-loader` rule must include `.svelte` files under `assets`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.svelte$/,
|
||||||
|
use: {
|
||||||
|
loader: 'svelte-loader',
|
||||||
|
options: { emitCss: false },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 processes the component's asset URL and emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development-only Svelte component:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
node.sources = sources
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
use:connectViewer
|
||||||
|
viewer-title="Project icons"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open the page containing Viewer. Do not import this development component from the production entry.
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# SVG Sprite for SvelteKit with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a SvelteKit application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "sveltekit@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite dev",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the SSR-safe Svelte component `AppIcon`.
|
||||||
|
|
||||||
|
Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in `src/routes/+page.svelte`:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { AppIcon } from '../../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. The component has no browser-only initialization, so the page can be rendered on the server. Vite emits `sprite.svg` as a separate production asset.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a development route such as `src/routes/svg-sprite/+page.svelte`. Load the custom element from an action so it is only registered in the browser:
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
const sources = [
|
||||||
|
() => import('../../../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
function connectViewer(node) {
|
||||||
|
void import('@gromlab/svg-sprites/viewer/element').then(() => {
|
||||||
|
node.sources = sources
|
||||||
|
node.viewerTitle = 'Project icons'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer use:connectViewer></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite`. The action does not run during SSR.
|
||||||
105
skills/svg-sprites/references/docs/en/guides/vue-vite.md
Normal file
105
skills/svg-sprites/references/docs/en/guides/vue-vite.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# SVG Sprite for Vue with Vite
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Vue application built with Vite.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "vue@vite",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"sprites": "npx --yes @gromlab/svg-sprites assets/app-icons/svg-sprite.config.json",
|
||||||
|
"predev": "npm run sprites",
|
||||||
|
"dev": "vite",
|
||||||
|
"prebuild": "npm run sprites",
|
||||||
|
"build": "vue-tsc --noEmit && vite build"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Vue component `AppIcon`.
|
||||||
|
|
||||||
|
Create the entry point `assets/app-icons/index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AppIcon } from '../assets/app-icons'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`.
|
||||||
|
|
||||||
|
Vite automatically includes the component styles and adds `sprite.svg` to the production build.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `svg-sprite.html` in the project root:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Project icons</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<gromlab-sprite-viewer viewer-title="Project icons"></gromlab-sprite-viewer>
|
||||||
|
<script type="module" src="/src/svg-sprite-debug.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `src/svg-sprite-debug.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from '../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `npm run dev` and open `/svg-sprite.html`.
|
||||||
|
|
||||||
|
Viewer is not required by `AppIcon` and is not loaded by the main application code.
|
||||||
126
skills/svg-sprites/references/docs/en/guides/vue-webpack.md
Normal file
126
skills/svg-sprites/references/docs/en/guides/vue-webpack.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# SVG Sprite for Vue with Webpack 5
|
||||||
|
|
||||||
|
A quick guide to creating an SVG sprite in a Vue application built with Webpack 5.
|
||||||
|
|
||||||
|
## Generate the sprite
|
||||||
|
|
||||||
|
Choose a directory for the future SVG sprite, for example `assets/app-icons`, and create `svg-sprite.config.json` inside it. In `input`, specify the path to existing SVG files relative to the configuration file. There is no need to move or copy the icons.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mode": "vue@webpack",
|
||||||
|
"name": "app",
|
||||||
|
"input": "../svg-icons/**/*.svg"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The package does not need to be a project dependency: generation runs through `npx`.
|
||||||
|
|
||||||
|
Add generation commands to `package.json`. Generated files are excluded from Git by default, so `predev` and `prebuild` rebuild the sprite before every start and build:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use the sprite
|
||||||
|
|
||||||
|
The value `name: "app"` creates the Vue component `AppIcon`. Create `assets/app-icons/index.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the component in your application:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { AppIcon } from '../assets/app-icons/index.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppIcon
|
||||||
|
icon="icon-name"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
role="img"
|
||||||
|
aria-label="Done"
|
||||||
|
style="color: #334155; --icon-color-2: #f59e0b"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `icon` prop accepts source SVG file names without the extension. A monochrome icon inherits `color`, while colors in a multicolor icon are overridden with `--icon-color-N`.
|
||||||
|
|
||||||
|
The component uses CSS Modules. If the project does not process them yet, install `style-loader` and `css-loader`, then add a rule with a default export:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev style-loader css-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.module\.css$/i,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: { modules: { namedExport: false } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5 automatically adds `sprite.svg` to the production build.
|
||||||
|
|
||||||
|
## Debug and preview
|
||||||
|
|
||||||
|
Viewer displays all icons on one page so you can check their rendering, change colors, and inspect the related CSS variables. It is only needed for development and is installed separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
Add Viewer to a development-only Vue component:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
|
||||||
|
const sources = [
|
||||||
|
() => import('../assets/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
:sources="sources"
|
||||||
|
viewer-title="Project icons"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure Vue Loader to treat `gromlab-sprite-viewer` as a custom element:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: 'vue-loader',
|
||||||
|
options: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag === 'gromlab-sprite-viewer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Render the Viewer component on your development page. Viewer is not required by `AppIcon`.
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
# Programmatic API
|
||||||
|
|
||||||
|
[Documentation index](../README.md)
|
||||||
|
|
||||||
|
The package is ESM-only and provides one Node.js generation API. The framework-neutral Viewer is available from `@gromlab/svg-sprites/viewer`, its auto-register entry from `@gromlab/svg-sprites/viewer/element`, and the React bridge from `@gromlab/svg-sprites/react`.
|
||||||
|
|
||||||
|
## `generateSprite`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { generateSprite } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
const result = await generateSprite(
|
||||||
|
'src/ui/file-manager/svg-sprite/svg-sprite.config.ts',
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
The result contains the sprite name, exact mode, mode-specific asset target, icon count, and absolute filesystem paths:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
result.name
|
||||||
|
result.mode
|
||||||
|
result.target
|
||||||
|
result.iconCount
|
||||||
|
result.rootDir
|
||||||
|
result.generatedDir
|
||||||
|
result.spritePath
|
||||||
|
result.manifestPath
|
||||||
|
```
|
||||||
|
|
||||||
|
Next.js modes additionally return `router` and `bundler`.
|
||||||
|
For bare `standalone`, `target` is `static`; standalone bundler and React modes
|
||||||
|
return `vite` or `webpack`; Next.js modes return their full exact mode as the
|
||||||
|
target. `standalone@server` returns `server`; its `spritePath` identifies the
|
||||||
|
standard content-addressed profile and `manifestPath` identifies the server manifest.
|
||||||
|
|
||||||
|
For static standalone mode, use `result.spritePath` in a build script to publish the
|
||||||
|
SVG under an application URL:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { copyFile } from 'node:fs/promises'
|
||||||
|
|
||||||
|
const result = await generateSprite('src/sprite/svg-sprite.config.ts', {
|
||||||
|
mode: 'standalone',
|
||||||
|
})
|
||||||
|
await copyFile(result.spritePath, 'dist/app-icons/sprite.svg')
|
||||||
|
```
|
||||||
|
|
||||||
|
`spritePath` is a filesystem path, not a browser URL. A deployment-neutral JSON
|
||||||
|
manifest is available through `result.manifestPath` and is copied independently.
|
||||||
|
|
||||||
|
The first argument accepts an absolute or relative path to an explicitly selected `.ts`, `.js`, or `.json` config file with any name. Passing a directory enables config-less mode and uses that directory as the sprite module root.
|
||||||
|
|
||||||
|
The second argument contains optional overrides and always takes precedence over the config:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await generateSprite('src/ui/file-manager/svg-sprite/custom-config.json', {
|
||||||
|
mode: 'react@webpack',
|
||||||
|
name: 'documents',
|
||||||
|
input: ['./assets', '../../shared/search.svg'],
|
||||||
|
transform: {
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
generatedNotice: false,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuration is resolved in this order:
|
||||||
|
|
||||||
|
```text
|
||||||
|
defaults → config → API overrides
|
||||||
|
```
|
||||||
|
|
||||||
|
For fully programmatic generation, pass a directory and provide the required `mode` and any other settings as overrides. `name` is optional: when omitted, it is inferred in kebab-case from the directory name, or from the parent directory when the module directory is named `svg-sprite` or `svg-sprites`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await generateSprite('src/ui/file-manager/svg-sprite', {
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'file-manager',
|
||||||
|
input: [
|
||||||
|
'../../shared/search.svg',
|
||||||
|
'../../shared/settings.svg',
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'file-manager',
|
||||||
|
description: 'File manager icons',
|
||||||
|
input: ['./icons', '../../shared/check.svg'],
|
||||||
|
transform: {
|
||||||
|
removeSize: true,
|
||||||
|
replaceColors: true,
|
||||||
|
addTransition: true,
|
||||||
|
},
|
||||||
|
generatedNotice: true,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`input` accepts one folder, SVG file, or glob pattern, or an array that combines them. When omitted, it defaults to `./icons`; relative paths start at the config directory.
|
||||||
|
|
||||||
|
`defineSpriteConfig` is an identity helper for TypeScript autocomplete. JavaScript can export the same object with `export default`, while JSON contains the object directly.
|
||||||
|
|
||||||
|
The public `ServerSvgInput`, `ServerSpriteManifest`, `ServerSpriteAsset`, and
|
||||||
|
`SpriteCompileProfile` types describe `standalone@server` inputs and release data.
|
||||||
|
A consumer uses the same API with `source: 'remote'` and one local path or HTTP(S)
|
||||||
|
manifest URL in `input`.
|
||||||
|
|
||||||
|
## Specialized wrappers
|
||||||
|
|
||||||
|
The specialized functions are available as wrappers around `generateSprite`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { generateNextSprite, generateReactSprite } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
await generateReactSprite('path/to/config.ts', 'vite')
|
||||||
|
await generateNextSprite('path/to/config.ts', {
|
||||||
|
router: 'app',
|
||||||
|
bundler: 'turbopack',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
An explicitly supplied target overrides `mode` from the file. Prefer `generateSprite` in new code.
|
||||||
|
|
||||||
|
## Config API
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import {
|
||||||
|
isSpriteMode,
|
||||||
|
loadSpriteConfig,
|
||||||
|
resolveSpriteConfig,
|
||||||
|
resolveSpriteConfigSource,
|
||||||
|
validateSpriteConfig,
|
||||||
|
} from '@gromlab/svg-sprites'
|
||||||
|
```
|
||||||
|
|
||||||
|
- `isSpriteMode(value)` checks whether a value is a supported exact mode.
|
||||||
|
- `loadSpriteConfig(file)` loads an explicitly selected `.ts`, `.js`, or `.json` file.
|
||||||
|
- `resolveSpriteConfigSource(source)` resolves a path as either a config file or a config-less directory.
|
||||||
|
- `validateSpriteConfig(value)` performs runtime validation.
|
||||||
|
- `resolveSpriteConfig(root, config, overrides)` merges values, applies defaults, and resolves paths relative to `root`.
|
||||||
|
|
||||||
|
## Low-level compiler
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import {
|
||||||
|
compileSprite,
|
||||||
|
compileSpriteContent,
|
||||||
|
createShapeTransform,
|
||||||
|
} from '@gromlab/svg-sprites'
|
||||||
|
```
|
||||||
|
|
||||||
|
These functions are intended for custom orchestration. Standard generation should use `generateSprite`.
|
||||||
|
|
||||||
|
## Viewer runtime
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
```
|
||||||
|
|
||||||
|
The browser entry registers `<gromlab-sprite-viewer>`. Bare standalone can also load the self-contained `dist/viewer-element.js` without a bundler.
|
||||||
|
|
||||||
|
For manual registration, import the runtime without the auto-register entry:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
|
||||||
|
defineSpriteViewerElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
Both Viewer entries export the registration function and the same public types:
|
||||||
|
`SpriteViewerColorTheme`, `SpriteViewerElement`, `SpriteViewerManifest`,
|
||||||
|
`SpriteViewerManifestColor`, `SpriteViewerManifestIcon`,
|
||||||
|
`SpriteViewerManifestLoader`, `SpriteViewerManifestModule`,
|
||||||
|
`SpriteViewerManifestUsage`, `SpriteViewerRemoteSource`, `SpriteViewerSource`,
|
||||||
|
and `SpriteViewerSources`. Only `@gromlab/svg-sprites/viewer/element` registers the
|
||||||
|
element as an import side effect.
|
||||||
|
|
||||||
|
The React bridge keeps the component API:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
```
|
||||||
|
|
||||||
|
`SpriteViewer` accepts generated manifests, remote standalone sources, lazy loaders, or an `import.meta.glob` result. The React entry contains `'use client'` and is intended for debug tools; production components are imported from local sprite modules.
|
||||||
717
skills/svg-sprites/references/docs/en/reference/technical.md
Normal file
717
skills/svg-sprites/references/docs/en/reference/technical.md
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
# Technical reference
|
||||||
|
|
||||||
|
[Documentation index](../README.md)
|
||||||
|
|
||||||
|
[JSON, JavaScript, and TypeScript configuration](../configuration.md)
|
||||||
|
|
||||||
|
Reference for the configuration, generated API, and behavior of `@gromlab/svg-sprites`. For step-by-step setup instructions, see the guide for your stack:
|
||||||
|
|
||||||
|
- [Bare standalone](../guides/standalone.md)
|
||||||
|
- [Standalone + Vite](../guides/standalone-vite.md)
|
||||||
|
- [Standalone + Webpack 5](../guides/standalone-webpack.md)
|
||||||
|
- [React + Vite](../guides/react-vite.md)
|
||||||
|
- [React + Webpack 5](../guides/react-webpack.md)
|
||||||
|
- [Next.js App Router + Turbopack](../guides/next-app-turbopack.md)
|
||||||
|
- [Next.js App Router + Webpack](../guides/next-app-webpack.md)
|
||||||
|
- [Next.js Pages Router + Turbopack](../guides/next-pages-turbopack.md)
|
||||||
|
- [Next.js Pages Router + Webpack](../guides/next-pages-webpack.md)
|
||||||
|
- [Vue + Vite](../guides/vue-vite.md)
|
||||||
|
- [Vue + Webpack](../guides/vue-webpack.md)
|
||||||
|
- [Nuxt + Vite](../guides/nuxt-vite.md)
|
||||||
|
- [Nuxt + Webpack](../guides/nuxt-webpack.md)
|
||||||
|
- [Svelte + Vite](../guides/svelte-vite.md)
|
||||||
|
- [Svelte + Webpack](../guides/svelte-webpack.md)
|
||||||
|
- [SvelteKit + Vite](../guides/sveltekit-vite.md)
|
||||||
|
- [Angular application builder](../guides/angular-application.md)
|
||||||
|
- [Angular + Webpack](../guides/angular-webpack.md)
|
||||||
|
- [Astro + Vite](../guides/astro-vite.md)
|
||||||
|
- [Solid + Vite](../guides/solid-vite.md)
|
||||||
|
- [Solid + Webpack](../guides/solid-webpack.md)
|
||||||
|
- [SolidStart + Vite](../guides/solid-start-vite.md)
|
||||||
|
- [Preact + Vite](../guides/preact-vite.md)
|
||||||
|
- [Preact + Webpack](../guides/preact-webpack.md)
|
||||||
|
- [Qwik + Vite](../guides/qwik-vite.md)
|
||||||
|
- [Lit + Vite](../guides/lit-vite.md)
|
||||||
|
- [Lit + Webpack](../guides/lit-webpack.md)
|
||||||
|
- [Alpine.js + Vite](../guides/alpine-vite.md)
|
||||||
|
- [Alpine.js + Webpack](../guides/alpine-webpack.md)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Node.js 18 or newer;
|
||||||
|
- the package is distributed as ESM and is loaded with `import`;
|
||||||
|
- React 18 or 19 is required only for React/Next generated components and `@gromlab/svg-sprites/react`;
|
||||||
|
- for typed package exports, use TypeScript 5+ with `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`.
|
||||||
|
|
||||||
|
Generation does not require a project dependency. Run the CLI through `npx`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx --yes @gromlab/svg-sprites path/to/svg-sprite.config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the package as a development dependency only when the project needs the
|
||||||
|
Viewer, config types, or the programmatic API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @gromlab/svg-sprites
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI and generation modes
|
||||||
|
|
||||||
|
The CLI accepts exactly one path: an explicitly selected config file or a directory for config-less generation:
|
||||||
|
|
||||||
|
```text
|
||||||
|
svg-sprites [options] <config-file-or-directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Environment | Mode |
|
||||||
|
|---|---|
|
||||||
|
| Static HTML / custom publishing | `standalone` |
|
||||||
|
| Standalone + Vite | `standalone@vite` |
|
||||||
|
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||||
|
| Server release | `standalone@server` |
|
||||||
|
| React + Vite | `react@vite` |
|
||||||
|
| React + Webpack 5 | `react@webpack` |
|
||||||
|
| Vue + Vite | `vue@vite` |
|
||||||
|
| Vue + Webpack | `vue@webpack` |
|
||||||
|
| Nuxt + Vite | `nuxt@vite` |
|
||||||
|
| Nuxt + Webpack | `nuxt@webpack` |
|
||||||
|
| Svelte + Vite | `svelte@vite` |
|
||||||
|
| Svelte + Webpack | `svelte@webpack` |
|
||||||
|
| SvelteKit + Vite | `sveltekit@vite` |
|
||||||
|
| Angular application builder | `angular@application` |
|
||||||
|
| Angular + Webpack | `angular@webpack` |
|
||||||
|
| Astro + Vite | `astro@vite` |
|
||||||
|
| Solid + Vite | `solid@vite` |
|
||||||
|
| Solid + Webpack | `solid@webpack` |
|
||||||
|
| SolidStart + Vite | `solid-start@vite` |
|
||||||
|
| Preact + Vite | `preact@vite` |
|
||||||
|
| Preact + Webpack | `preact@webpack` |
|
||||||
|
| Qwik + Vite | `qwik@vite` |
|
||||||
|
| Lit + Vite | `lit@vite` |
|
||||||
|
| Lit + Webpack | `lit@webpack` |
|
||||||
|
| Alpine.js + Vite | `alpine@vite` |
|
||||||
|
| Alpine.js + Webpack | `alpine@webpack` |
|
||||||
|
| Next.js App Router + Turbopack | `next@app/turbopack` |
|
||||||
|
| Next.js App Router + Webpack 5 | `next@app/webpack` |
|
||||||
|
| Next.js Pages Router + Turbopack | `next@pages/turbopack` |
|
||||||
|
| Next.js Pages Router + Webpack 5 | `next@pages/webpack` |
|
||||||
|
|
||||||
|
The config file may have any name and use the `.ts`, `.js`, or `.json` extension. The CLI does not discover it by convention: pass the file explicitly. The recommended name is `svg-sprite.config.json`.
|
||||||
|
|
||||||
|
When a directory is passed, all settings come from CLI options. When a config file is passed, CLI options override the file. The full order is `defaults → config → CLI`.
|
||||||
|
|
||||||
|
`--help` and `-h` print usage information without requiring a path. Generation options are `--mode`, `--source <local|remote>`, `--name`, `--description`, repeatable `--input <path-or-glob>`, plus the `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition`, and `--generated-notice`/`--no-generated-notice` pairs. Transform flags override individual fields, while supplying at least one `--input` replaces the complete config `input` value.
|
||||||
|
|
||||||
|
Quote CLI glob patterns with single quotes so the shell does not expand them before the generator receives them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
svg-sprites --input './icons/**/*.svg' --input '!./icons/legacy/**' svg-sprite.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
The mode must match the application's publishing strategy. Bare `standalone` leaves the public URL to the application; Vite and Webpack modes generate bundler-specific SVG asset integration.
|
||||||
|
|
||||||
|
## Unified configuration
|
||||||
|
|
||||||
|
Each config file defines one independent sprite.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'next@app/turbopack',
|
||||||
|
name: 'app',
|
||||||
|
description: 'Shared application icons',
|
||||||
|
input: [
|
||||||
|
'./local-icons',
|
||||||
|
'../../assets/icons/*.svg',
|
||||||
|
'!../../assets/icons/deprecated-*.svg',
|
||||||
|
],
|
||||||
|
transform: {
|
||||||
|
removeSize: true,
|
||||||
|
replaceColors: true,
|
||||||
|
addTransition: true,
|
||||||
|
},
|
||||||
|
generatedNotice: true,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Type | Default | Purpose |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `mode` | `SpriteMode` | None | Generation mode; may be supplied by CLI/API |
|
||||||
|
| `source` | `local \| remote` | `local` | Source SVG files or a ready server manifest |
|
||||||
|
| `name` | `string` | Derived from the directory | Sprite name; in modes with a component, it also determines the component and public type names |
|
||||||
|
| `description` | `string` | None | Description for types and the debug manifest |
|
||||||
|
| `input` | `SpriteInput \| SpriteInput[]` | `./icons` | Local SVG sources, server HTTP descriptors, or one remote manifest, depending on mode and source |
|
||||||
|
| `transform` | `TransformOptions` | All enabled | SVG preparation settings |
|
||||||
|
| `generatedNotice` | `boolean` | `true` | Full or abbreviated warning in generated files |
|
||||||
|
|
||||||
|
With `source: 'remote'`, `input` contains one local path or HTTP(S) URL to a
|
||||||
|
manifest produced by `standalone@server`. A remote consumer config may contain
|
||||||
|
only `mode`, `source`, and `input`: the name, description, transforms, and generated
|
||||||
|
notice are verified and inherited from the server manifest. Generation downloads
|
||||||
|
the profile required by the exact consumer mode and verifies its SHA-256 and byte
|
||||||
|
length before codegen. There is no runtime network dependency on the server manifest.
|
||||||
|
|
||||||
|
### Sprite name
|
||||||
|
|
||||||
|
`name` is written in kebab-case and must start with an ASCII letter:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app → AppIcon
|
||||||
|
file-manager → FileManagerIcon
|
||||||
|
```
|
||||||
|
|
||||||
|
If `name` is omitted, the generator converts the directory name to kebab-case. For a directory named `svg-sprite` or `svg-sprites`, the parent directory's name is used.
|
||||||
|
|
||||||
|
### Icon sources
|
||||||
|
|
||||||
|
`SpriteConfig.input` is optional and has the type `string | string[]`. When it is omitted, the source is the literal `./icons` folder relative to the config directory. In config-less mode, relative paths start at the directory passed to the CLI or API.
|
||||||
|
|
||||||
|
Each positive string may be a literal folder, a literal `.svg` file, or a glob pattern. A literal folder includes only its immediate `*.svg` children. Use an explicit pattern such as `icons/**/*.svg` to traverse nested directories.
|
||||||
|
|
||||||
|
An array combines all positive sources. A pattern prefixed with `!` excludes its matches from the combined result globally, regardless of which positive source included them.
|
||||||
|
|
||||||
|
Supported glob syntax includes:
|
||||||
|
|
||||||
|
| Syntax | Meaning |
|
||||||
|
|---|---|
|
||||||
|
| `*` | Any characters within one path segment |
|
||||||
|
| `**` | Any number of nested directories |
|
||||||
|
| `?` | One character within a path segment |
|
||||||
|
| `{a,b}` | Either alternative |
|
||||||
|
| `[abc]` | One character from the set or range |
|
||||||
|
| `!pattern` | Exclude matches from the full combined input |
|
||||||
|
|
||||||
|
Every positive source or pattern must find at least one SVG, otherwise generation fails. Duplicate paths are removed and the final file list is sorted deterministically. Different SVG files with the same basename remain a conflict because the basename defines the public icon name.
|
||||||
|
|
||||||
|
### Server SVG inputs
|
||||||
|
|
||||||
|
`standalone@server` accepts the same local strings plus HTTP(S) descriptors in its
|
||||||
|
`input` array:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
name: 'brand-logo',
|
||||||
|
url: 'https://assets.example.com/brand-logo.svg',
|
||||||
|
sha256: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`name` becomes the public icon name. `sha256` is optional and, when present, is
|
||||||
|
checked against the downloaded bytes. URL credentials and active SVG content such
|
||||||
|
as scripts, event handlers, `foreignObject`, or a doctype are rejected. One HTTP
|
||||||
|
source is limited to 2 MiB, all combined sources to 25 MiB, and requests time out
|
||||||
|
after 15 seconds. Local and HTTP entries share one namespace, so duplicate icon
|
||||||
|
names fail generation.
|
||||||
|
|
||||||
|
## Generated module
|
||||||
|
|
||||||
|
After generation, a React or Next.js sprite directory looks like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app-icons/
|
||||||
|
├── .gitignore
|
||||||
|
├── svg-sprite.config.json
|
||||||
|
├── index.ts # optional user-owned barrel
|
||||||
|
└── .svg-sprite/
|
||||||
|
├── index.js
|
||||||
|
├── index.d.ts
|
||||||
|
├── icon-data.js
|
||||||
|
├── icon-data.d.ts
|
||||||
|
├── sprite.svg
|
||||||
|
├── svg-sprite.manifest.js
|
||||||
|
├── svg-sprite.manifest.d.ts
|
||||||
|
└── react/
|
||||||
|
├── react-component.js
|
||||||
|
├── react-component.d.ts
|
||||||
|
└── react-component.module.css
|
||||||
|
```
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `.svg-sprite/index.js` | Mode-specific production facade and runtime icon-name list |
|
||||||
|
| `.svg-sprite/index.d.ts` | Public declarations for the facade, component, and icon-name union |
|
||||||
|
| `.svg-sprite/svg-sprite.manifest.js` | Debug metadata and the asset URL for `SpriteViewer` |
|
||||||
|
| `.svg-sprite/sprite.svg` | Compiled SVG sprite |
|
||||||
|
| `.svg-sprite/react/react-component.js` | React component runtime without TypeScript or JSX |
|
||||||
|
| `.svg-sprite/react/react-component.d.ts` | React component props, style, and declaration |
|
||||||
|
| `.svg-sprite/react/react-component.module.css` | Styles for the React implementation |
|
||||||
|
| `.svg-sprite/icon-data.js` | Runtime icon-name list and internal IDs |
|
||||||
|
| `.svg-sprite/*.d.ts` | TypeScript declarations for the corresponding JavaScript modules |
|
||||||
|
|
||||||
|
Standalone contracts do not create `react/`. Bare `standalone` contains only the
|
||||||
|
runtime asset and deployment-neutral manifest data:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.svg-sprite/
|
||||||
|
├── sprite.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`standalone@vite` and `standalone@webpack` additionally create `index.*`,
|
||||||
|
`icon-data.*`, and a resolved `svg-sprite.manifest.*`. Their facade contains a
|
||||||
|
native generated Web Component with no external runtime dependencies. Bare
|
||||||
|
`standalone` intentionally does not generate a JavaScript component.
|
||||||
|
|
||||||
|
`standalone@server` creates a publishable release without JavaScript runtime or
|
||||||
|
`.gitignore`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.svg-sprite/
|
||||||
|
├── sprite.<content-hash>.svg
|
||||||
|
├── sprite-root-viewbox.<content-hash>.svg
|
||||||
|
└── svg-sprite.manifest.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The manifest identifies both compile profiles by relative `href`, full SHA-256,
|
||||||
|
and byte length. Publish the complete directory atomically; consumers resolve each
|
||||||
|
profile relative to the manifest URL or local manifest path.
|
||||||
|
|
||||||
|
The generator fully manages `.svg-sprite` and replaces the whole directory on every generation through a staged write with rollback on replacement failure. Any files added inside it are deleted during the next generation. Keep user-owned files alongside it, for example in a root `index.ts` barrel:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export * from './.svg-sprite/index.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Standalone Web Component and TypeScript
|
||||||
|
|
||||||
|
In `standalone@vite` and `standalone@webpack`, a sprite with `name: 'app'`
|
||||||
|
exports the `defineAppIconElement()` registration function and the `<app-icon>`
|
||||||
|
tag:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineAppIconElement } from '@/ui/app-icons'
|
||||||
|
|
||||||
|
defineAppIconElement()
|
||||||
|
```
|
||||||
|
|
||||||
|
After registration, use the element in HTML:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="search" aria-hidden="true"></app-icon>
|
||||||
|
|
||||||
|
<app-icon
|
||||||
|
icon="settings"
|
||||||
|
role="img"
|
||||||
|
aria-label="Settings"
|
||||||
|
></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
The component renders `<svg><use>` in an open Shadow DOM, selects the internal
|
||||||
|
ID and `viewBox`, and obtains the asset URL through the corresponding Vite or
|
||||||
|
Webpack mechanism. The host defaults to `1em × 1em`; set `class`, `style`,
|
||||||
|
`color`, and `--icon-color-N` with ordinary CSS.
|
||||||
|
|
||||||
|
The generated `HTMLElementTagNameMap` types the property API:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const icon = document.createElement('app-icon')
|
||||||
|
|
||||||
|
icon.icon = 'search'
|
||||||
|
icon.icon = 'unknown' // TypeScript error
|
||||||
|
```
|
||||||
|
|
||||||
|
TypeScript does not validate attribute values in plain HTML. Therefore an
|
||||||
|
unknown `icon="unknown"` is also validated at runtime: the component hides its
|
||||||
|
inner SVG and reports an error instead of creating a `#undefined` fragment.
|
||||||
|
Calling `defineAppIconElement()` repeatedly is safe for the same sprite; a
|
||||||
|
different element already registered as `<app-icon>` causes an error.
|
||||||
|
|
||||||
|
## React component and TypeScript
|
||||||
|
|
||||||
|
A sprite with `name: 'app'` exports:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export { AppIcon, appIconNames }
|
||||||
|
export type { AppIconName, AppIconProps, AppIconStyle }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Icon names
|
||||||
|
|
||||||
|
SVG file names become valid `icon` values:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" />
|
||||||
|
<AppIcon icon="unknown" /> // TypeScript error
|
||||||
|
```
|
||||||
|
|
||||||
|
The runtime list contains the same values:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { appIconNames } from '@/ui/app-icons'
|
||||||
|
|
||||||
|
// readonly ['search', 'settings', 'user']
|
||||||
|
```
|
||||||
|
|
||||||
|
Names containing spaces or other characters that are unsafe in SVG IDs remain part of the public API. For the internal fragment ID, the generator creates a stable, safe hash:
|
||||||
|
|
||||||
|
```text
|
||||||
|
folder open.svg → icon="folder open" → id="icon-<stable-hash>"
|
||||||
|
```
|
||||||
|
|
||||||
|
For these names, use the generated component or the `id` from the debug manifest instead of constructing the fragment ID manually.
|
||||||
|
|
||||||
|
### SVG attributes
|
||||||
|
|
||||||
|
By default, the component renders an `<svg>` and accepts standard SVG attributes:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="search"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
color="rebeccapurple"
|
||||||
|
className="searchIcon"
|
||||||
|
aria-label="Search"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The component does not add accessibility semantics automatically. Pass appropriate `aria-*` attributes, a `role`, or a label based on the icon's purpose.
|
||||||
|
|
||||||
|
### Wrapper
|
||||||
|
|
||||||
|
`wrapped` renders a `<span>` containing the SVG. In this mode, the remaining props apply to the `<span>`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" wrapped className="iconWrapper" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Typed CSS custom properties
|
||||||
|
|
||||||
|
`AppIconStyle` extends `CSSProperties` and supports properties in the form `--icon-color-N`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon
|
||||||
|
icon="user"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#2563eb',
|
||||||
|
'--icon-color-2': '#dbeafe',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiple sprites
|
||||||
|
|
||||||
|
Each directory with a configuration creates an independent mode-specific contract. Framework modes generate their native component and declarations, standalone bundler modes generate a Web Component and declarations, and bare `standalone` generates an SVG and JSON manifest:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app-icons → AppIcon → shared icons
|
||||||
|
analytics-icons → AnalyticsIcon → analytics page icons
|
||||||
|
editor-icons → EditorIcon → editor icons
|
||||||
|
```
|
||||||
|
|
||||||
|
The same source SVG can be added to multiple configurations through `input`. You do not need to copy the file into each sprite directory.
|
||||||
|
|
||||||
|
For multiple sprites, add a separate CLI command for each directory or combine the commands in a shared npm script.
|
||||||
|
|
||||||
|
## Formats and rendering methods
|
||||||
|
|
||||||
|
All current modes generate the `stack` format.
|
||||||
|
|
||||||
|
| Format | `<svg><use>` | `<img>` | CSS background |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| `stack` | Yes | Yes | Yes |
|
||||||
|
|
||||||
|
### Generated component
|
||||||
|
|
||||||
|
Use the generated native component documented by the selected exact-mode guide. It knows the internal IDs, constructs the URL, and provides a TypeScript API. React and Next.js use it like this:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" width={24} height={24} />
|
||||||
|
```
|
||||||
|
|
||||||
|
For `standalone@vite` and `standalone@webpack`, use the generated Web Component:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<app-icon icon="search" style="font-size: 24px"></app-icon>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manually with `<svg><use>`
|
||||||
|
|
||||||
|
How you obtain `spriteUrl` depends on the bundler.
|
||||||
|
|
||||||
|
Static HTML after the application publishes `.svg-sprite/sprite.svg`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<svg aria-hidden="true">
|
||||||
|
<use href="/assets/icons.svg#search"></use>
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Standalone Vite/Webpack provides generated `getAppIconHref()` and an internal ID
|
||||||
|
map. Do not construct fragments from unsafe file names manually.
|
||||||
|
|
||||||
|
Vite:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import spriteUrl from './.svg-sprite/sprite.svg?no-inline'
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack 5, Turbopack, and Next.js:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const spriteUrl = new URL('./.svg-sprite/sprite.svg', import.meta.url).href
|
||||||
|
```
|
||||||
|
|
||||||
|
After obtaining the URL, use it in JSX:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<svg width="24" height="24" aria-label="Search">
|
||||||
|
<use href={`${spriteUrl}#search`} />
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
For names that are unsafe as SVG IDs, use the internal `id` from the manifest.
|
||||||
|
|
||||||
|
### With `<img>`
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<img src={`${spriteUrl}#search`} width={24} height={24} alt="Search" />
|
||||||
|
```
|
||||||
|
|
||||||
|
An SVG inside `<img>` is isolated from the page's CSS. Setting `color` or `--icon-color-N` on the outer element does not change its internal colors.
|
||||||
|
|
||||||
|
### With CSS
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
background: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For a single-color silhouette, you can use a mask:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
background-color: currentColor;
|
||||||
|
mask: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A mask does not preserve original colors, gradients, or differences between `fill` and `stroke`.
|
||||||
|
|
||||||
|
The path in CSS is resolved relative to the CSS file itself. In these examples, the CSS file is next to `svg-sprite.config.ts`.
|
||||||
|
|
||||||
|
## Assets and caching
|
||||||
|
|
||||||
|
The generated component or standalone facade passes the SVG to the bundler as a separate asset:
|
||||||
|
|
||||||
|
- Vite uses a static import with `?no-inline`;
|
||||||
|
- Webpack 5, Turbopack, and Next.js use `new URL(..., import.meta.url)`;
|
||||||
|
- SVG path data is not serialized into generated JavaScript.
|
||||||
|
|
||||||
|
Bare `standalone` does not participate in an asset pipeline: the application copies
|
||||||
|
or publishes `sprite.svg` and owns its URL, versioning, and cache policy.
|
||||||
|
|
||||||
|
With standard asset naming, the bundler adds a content hash:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/assets/sprite-<hash>.svg
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows the SVG to be cached separately from JavaScript. Changing React code does not change the sprite contents, while changing icons creates a new asset version.
|
||||||
|
|
||||||
|
HTTP cache headers, CDN behavior, and `Cache-Control` are configured by the application or hosting platform. With Webpack, the final file name depends on the project's `assetModuleFilename`.
|
||||||
|
|
||||||
|
## SVG transformations
|
||||||
|
|
||||||
|
All transformations are enabled by default and can be configured independently:
|
||||||
|
|
||||||
|
| Option | Behavior |
|
||||||
|
|---|---|
|
||||||
|
| `removeSize` | Removes `width` and `height` from the root `<svg>` while preserving an existing `viewBox` |
|
||||||
|
| `replaceColors` | Replaces detected `fill` and `stroke` values with `--icon-color-N` |
|
||||||
|
| `addTransition` | Adds transitions for `fill` and `stroke` to colored elements and generated styles |
|
||||||
|
|
||||||
|
To disable an individual operation:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'next@app/turbopack',
|
||||||
|
transform: {
|
||||||
|
removeSize: false,
|
||||||
|
replaceColors: false,
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Source SVG files are not modified. Transformations apply only to the generated sprite contents.
|
||||||
|
|
||||||
|
## Color management
|
||||||
|
|
||||||
|
### Monochrome icons
|
||||||
|
|
||||||
|
If one color is detected, its fallback becomes `currentColor`:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
stroke="var(--icon-color-1, currentColor)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the color through a prop or CSS:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<AppIcon icon="search" color="rebeccapurple" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multicolor icons
|
||||||
|
|
||||||
|
Each unique color gets its own custom property with the original color as its fallback:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
fill="var(--icon-color-1, #798198)"
|
||||||
|
fill="var(--icon-color-2, #ffffff)"
|
||||||
|
fill="var(--icon-color-3, #129d9d)"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can override only the values you need:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.icon {
|
||||||
|
--icon-color-1: #4b5563;
|
||||||
|
--icon-color-3: #14b8a6;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
- `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced;
|
||||||
|
- colors in `fill`, `stroke`, and inline `style` attributes are handled most reliably;
|
||||||
|
- CSS classes and external stylesheets inside the SVG are not the primary transformation use case;
|
||||||
|
- `url(#...)` values may be replaced along with colors, so gradients and patterns require a separate sprite with `replaceColors: false`;
|
||||||
|
- masks, filters, and complex internal CSS rules require visual verification;
|
||||||
|
- page CSS custom properties are available through `<svg><use>`, but not inside `<img>` or a CSS background.
|
||||||
|
|
||||||
|
For a complex icon, you can disable `replaceColors` in a separate sprite configuration.
|
||||||
|
|
||||||
|
## SpriteViewer
|
||||||
|
|
||||||
|
The Viewer uses one Shadow DOM Web Component for every mode. React and future framework components are bridges to that same element, so the visuals and behavior are not duplicated.
|
||||||
|
|
||||||
|
Bare `standalone` loads the self-contained browser bundle and supplies the JSON manifest URL and the published SVG URL:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="https://unpkg.com/@gromlab/svg-sprites@<version>/dist/viewer-element.js"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<gromlab-sprite-viewer
|
||||||
|
viewer-title="Project icons"
|
||||||
|
manifest-url="/app-icons/manifest.json"
|
||||||
|
sprite-url="/app-icons/sprite.svg"
|
||||||
|
></gromlab-sprite-viewer>
|
||||||
|
```
|
||||||
|
|
||||||
|
`viewer-element.js` has no additional runtime files and can be copied with the other static assets for self-hosting.
|
||||||
|
|
||||||
|
`standalone@vite` and `standalone@webpack` register the same element through an npm entry and pass the generated JS manifest through the `sources` property:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import '@gromlab/svg-sprites/viewer/element'
|
||||||
|
import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer'
|
||||||
|
import spriteManifest from './svg-sprite/.svg-sprite/svg-sprite.manifest.js'
|
||||||
|
|
||||||
|
const viewer = document.querySelector<SpriteViewerElement>('gromlab-sprite-viewer')!
|
||||||
|
viewer.sources = [spriteManifest]
|
||||||
|
```
|
||||||
|
|
||||||
|
React and Next.js keep the component API:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
```
|
||||||
|
|
||||||
|
It accepts ready-made manifests, remote standalone sources, an array of lazy loaders, or a record in the format returned by `import.meta.glob`.
|
||||||
|
|
||||||
|
Vite:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||||
|
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||||
|
|
||||||
|
const sources = import.meta.glob<SpriteManifestModule>(
|
||||||
|
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||||
|
)
|
||||||
|
|
||||||
|
export const IconsDebugPage = () => (
|
||||||
|
<SpriteViewer sources={sources} title="Project icons" />
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Webpack and Next.js:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const sources = [
|
||||||
|
() => import('@/ui/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
() => import('@/features/analytics/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||||
|
]
|
||||||
|
|
||||||
|
export const IconsDebugPage = () => (
|
||||||
|
<SpriteViewer sources={sources} />
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
The Viewer displays groups, search, `viewBox`, CSS custom properties, and fallback colors. Framework manifests get their framework-specific tab plus SVG, IMG, and CSS; standalone manifests get SVG, IMG, and CSS. You can change color values in the interface and immediately inspect the result.
|
||||||
|
|
||||||
|
### Viewer theme
|
||||||
|
|
||||||
|
By default, `colorTheme="auto"` follows `prefers-color-scheme`. You can explicitly pass `light` or `dark`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<SpriteViewer sources={sources} colorTheme="dark" />
|
||||||
|
```
|
||||||
|
|
||||||
|
To synchronize it with the application theme:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<SpriteViewer
|
||||||
|
sources={sources}
|
||||||
|
colorTheme={appTheme}
|
||||||
|
onColorThemeChange={setAppTheme}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
`@gromlab/svg-sprites/react` contains `'use client'` and renders the Web Component host; its internal Shadow DOM is created after the browser runtime loads. In the Next.js App Router, place the Viewer inside a separate Client Component boundary and use it only on a debug route or in an internal tool.
|
||||||
|
|
||||||
|
## Generated files, Git, and CI
|
||||||
|
|
||||||
|
Every mode except bare `standalone` creates a local `.gitignore` for:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/.svg-sprite/
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit the local `.gitignore` to the repository once. It excludes the other generated files, so generation must run before commands that import the sprite module:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
CI must run generation before building or type-checking. Pin `@gromlab/svg-sprites` to an exact version when the CI toolchain must be reproducible. A local package installation is not required unless CI also uses the Viewer, package config types, or the programmatic API.
|
||||||
|
|
||||||
|
Bare `standalone` does not create a `.gitignore` and preserves a user-owned file. If a managed `.gitignore` remains after another mode, bare mode removes it. In every other mode, the generator refuses to overwrite a user-owned `.gitignore` without a generated marker. The root `index.ts` remains user-owned and may re-export the generated API.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- In every mode except bare `standalone`, missing `.svg-sprite/index.js`: run the generation script before importing the generated module.
|
||||||
|
- Source not found: pass an existing config file or sprite module directory.
|
||||||
|
- Mode missing: add `mode` to the config or pass `--mode`.
|
||||||
|
- Icon missing from the type: check `input`, the `.svg` extension, glob exclusions, and whether nested folders require `**/*.svg`.
|
||||||
|
- Name conflict: two different SVG files have the same basename; rename one of them.
|
||||||
|
- `Refusing to overwrite a user file`: the sprite module root contains a user-owned `.gitignore` that the generator cannot replace.
|
||||||
|
- The icon does not change color: use `<svg><use>` or the generated component and check `replaceColors`.
|
||||||
|
- Webpack emits an incorrect URL: check Asset Modules, `output.publicPath`, and SVG loaders.
|
||||||
|
- Static sprite returns 404: check the post-generation copy or server alias, and do not put a filesystem `spritePath` into HTML.
|
||||||
|
- The Viewer cannot find the sprite: in bundler modes, check the path to `.svg-sprite/svg-sprite.manifest.js`; for bare `standalone`, check the published `svg-sprite.manifest.json` and `sprite.svg` URLs. Run generation before starting the application.
|
||||||
|
- Build and mode do not match: use the target that corresponds to the actual bundler.
|
||||||
|
|
||||||
|
For custom orchestration and low-level compilation, see the [Programmatic API](programmatic-api.md).
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# AI skills
|
# AI skills
|
||||||
|
|
||||||
Исходники обязательного контекста английского и русского skills находятся в `skills/svg-sprites/src/{en,ru}/`. Готовые переносимые артефакты генерируются в `skills/artifacts/`, игнорируются Git и упаковываются в ZIP во время release workflow.
|
Исходники обязательного контекста английского и русского skills находятся в `src/skills/svg-sprites/src/{en,ru}/`. Готовые переносимые артефакты генерируются в корневой каталог `skills/`, версионируются для установки через `npx skills add` и упаковываются в ZIP во время release workflow.
|
||||||
|
|
||||||
Обе языковые версии имеют симметричную single-file структуру:
|
Обе языковые версии имеют симметричную single-file структуру:
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ src/{en,ru}/
|
|||||||
<!-- include: ./fragments/mode-selection.md -->
|
<!-- include: ./fragments/mode-selection.md -->
|
||||||
```
|
```
|
||||||
|
|
||||||
Include раскрываются рекурсивно, путь считается относительно включающего файла. Циклы, отсутствующие файлы, выход за `skills/svg-sprites/`, frontmatter во фрагментах и нераскрытые include завершают сборку ошибкой. Заголовки не сдвигаются автоматически: entry содержит единственный `# H1`, inline-фрагменты начинаются с `##`.
|
Include раскрываются рекурсивно, путь считается относительно включающего файла. Циклы, отсутствующие файлы, выход за `src/skills/svg-sprites/`, frontmatter во фрагментах и нераскрытые include завершают сборку ошибкой. Заголовки не сдвигаются автоматически: entry содержит единственный `# H1`, inline-фрагменты начинаются с `##`.
|
||||||
|
|
||||||
## Локальная сборка
|
## Локальная сборка
|
||||||
|
|
||||||
@@ -31,4 +31,4 @@ Include раскрываются рекурсивно, путь считаетс
|
|||||||
npm run build:skill
|
npm run build:skill
|
||||||
```
|
```
|
||||||
|
|
||||||
Команда собирает и валидирует обе языковые версии, затем записывает их в игнорируемый каталог `skills/artifacts/`. Сборщик проверяет точный список файлов, безопасные пути, symlink, Markdown fences, локальные ссылки и anchors, единственный H1, frontmatter, размер основного документа и отсутствие `TODO`.
|
Команда собирает и валидирует обе языковые версии, затем атомарно заменяет корневой каталог `skills/`. Сборщик проверяет точный список файлов, безопасные пути, symlink, Markdown fences, локальные ссылки и anchors, единственный H1, frontmatter, размер основного документа и отсутствие `TODO`. `npm run check:skill` дополнительно проверяет, что версионируемые артефакты совпадают с результатом сборки.
|
||||||
@@ -15,7 +15,9 @@ import { fileURLToPath } from 'node:url'
|
|||||||
import configs from './skill.config.mjs'
|
import configs from './skill.config.mjs'
|
||||||
|
|
||||||
const skillDir = path.dirname(fileURLToPath(import.meta.url))
|
const skillDir = path.dirname(fileURLToPath(import.meta.url))
|
||||||
const artifactsDir = path.resolve(skillDir, '../artifacts')
|
const repositoryRoot = path.resolve(skillDir, '../../..')
|
||||||
|
const outputRoot = path.join(repositoryRoot, 'skills')
|
||||||
|
const temporaryParent = path.join(repositoryRoot, '.tmp')
|
||||||
const includePattern = /<!--\s*include:\s*(.*?)\s*-->/g
|
const includePattern = /<!--\s*include:\s*(.*?)\s*-->/g
|
||||||
const isCheck = process.argv.slice(2).includes('--check')
|
const isCheck = process.argv.slice(2).includes('--check')
|
||||||
|
|
||||||
@@ -114,7 +116,7 @@ function renderSkill(config, document) {
|
|||||||
return [
|
return [
|
||||||
...frontmatter,
|
...frontmatter,
|
||||||
'',
|
'',
|
||||||
`<!-- Generated from skills/svg-sprites/${document.entry}. Do not edit manually. -->`,
|
`<!-- Generated from src/skills/svg-sprites/${document.entry}. Do not edit manually. -->`,
|
||||||
'',
|
'',
|
||||||
body,
|
body,
|
||||||
'',
|
'',
|
||||||
@@ -168,8 +170,9 @@ function prepareConfig(config) {
|
|||||||
throw new Error(`Skill documents must be a non-empty array: ${config.name}`)
|
throw new Error(`Skill documents must be a non-empty array: ${config.name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputDir = path.resolve(skillDir, config.output)
|
assertSafeRelativePath(config.output)
|
||||||
assertInside(artifactsDir, outputDir)
|
const outputDir = path.resolve(outputRoot, config.output)
|
||||||
|
assertInside(outputRoot, outputDir)
|
||||||
|
|
||||||
const documents = config.documents.map((document) => {
|
const documents = config.documents.map((document) => {
|
||||||
assertSafeRelativePath(document.entry)
|
assertSafeRelativePath(document.entry)
|
||||||
@@ -190,7 +193,14 @@ function prepareConfig(config) {
|
|||||||
targets.add(entry.to)
|
targets.add(entry.to)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { config, outputDir, documents, copies, expectedFiles: [...targets].sort() }
|
return {
|
||||||
|
config,
|
||||||
|
outputDir,
|
||||||
|
outputPath: path.relative(outputRoot, outputDir),
|
||||||
|
documents,
|
||||||
|
copies,
|
||||||
|
expectedFiles: [...targets].sort(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeArtifactFile(targetDir, relativePath, content) {
|
function writeArtifactFile(targetDir, relativePath, content) {
|
||||||
@@ -305,10 +315,46 @@ function validateArtifact(prepared, skillRoot) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertArtifactDirectory(directory) {
|
||||||
|
if (!existsSync(directory)) {
|
||||||
|
throw new Error('Generated skills are missing. Run npm run build:skill.')
|
||||||
|
}
|
||||||
|
const stats = lstatSync(directory)
|
||||||
|
if (stats.isSymbolicLink() || !stats.isDirectory()) {
|
||||||
|
throw new Error(`Skill output must be a directory without symlinks: ${directory}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertArtifactsCurrent(stagedRoot) {
|
||||||
|
assertArtifactDirectory(outputRoot)
|
||||||
|
const expectedFiles = listFiles(stagedRoot).sort()
|
||||||
|
const actualFiles = listFiles(outputRoot).sort()
|
||||||
|
const expectedSet = new Set(expectedFiles)
|
||||||
|
const actualSet = new Set(actualFiles)
|
||||||
|
const missingFiles = expectedFiles.filter((file) => !actualSet.has(file))
|
||||||
|
const unexpectedFiles = actualFiles.filter((file) => !expectedSet.has(file))
|
||||||
|
const changedFiles = expectedFiles.filter((file) => (
|
||||||
|
actualSet.has(file)
|
||||||
|
&& !readFileSync(path.join(stagedRoot, file)).equals(readFileSync(path.join(outputRoot, file)))
|
||||||
|
))
|
||||||
|
|
||||||
|
if (missingFiles.length || unexpectedFiles.length || changedFiles.length) {
|
||||||
|
const details = [
|
||||||
|
...missingFiles.map((file) => `Missing: ${file}`),
|
||||||
|
...unexpectedFiles.map((file) => `Unexpected: ${file}`),
|
||||||
|
...changedFiles.map((file) => `Changed: ${file}`),
|
||||||
|
]
|
||||||
|
throw new Error(`Generated skills are out of date. Run npm run build:skill.\n${details.join('\n')}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function replaceDirectory(stagedDir, outputDir) {
|
function replaceDirectory(stagedDir, outputDir) {
|
||||||
const backupDir = `${outputDir}.backup-${process.pid}`
|
const backupDir = path.join(path.dirname(stagedDir), `.skills-backup-${process.pid}`)
|
||||||
rmSync(backupDir, { recursive: true, force: true })
|
rmSync(backupDir, { recursive: true, force: true })
|
||||||
if (existsSync(outputDir)) renameSync(outputDir, backupDir)
|
if (existsSync(outputDir)) {
|
||||||
|
assertArtifactDirectory(outputDir)
|
||||||
|
renameSync(outputDir, backupDir)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
renameSync(stagedDir, outputDir)
|
renameSync(stagedDir, outputDir)
|
||||||
rmSync(backupDir, { recursive: true, force: true })
|
rmSync(backupDir, { recursive: true, force: true })
|
||||||
@@ -339,21 +385,23 @@ for (const [index, prepared] of preparedConfigs.entries()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdirSync(artifactsDir, { recursive: true })
|
mkdirSync(temporaryParent, { recursive: true })
|
||||||
const temporaryRoot = mkdtempSync(path.join(artifactsDir, '.skills-build-'))
|
const temporaryRoot = mkdtempSync(path.join(temporaryParent, 'skills-build-'))
|
||||||
try {
|
try {
|
||||||
for (const prepared of preparedConfigs) {
|
for (const prepared of preparedConfigs) {
|
||||||
const stagedDir = path.join(temporaryRoot, prepared.config.name)
|
const stagedDir = path.join(temporaryRoot, prepared.outputPath)
|
||||||
buildSkill(prepared, stagedDir)
|
buildSkill(prepared, stagedDir)
|
||||||
validateArtifact(prepared, stagedDir)
|
validateArtifact(prepared, stagedDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const prepared of preparedConfigs) {
|
if (isCheck) {
|
||||||
const stagedDir = path.join(temporaryRoot, prepared.config.name)
|
assertArtifactsCurrent(temporaryRoot)
|
||||||
if (isCheck) {
|
for (const prepared of preparedConfigs) {
|
||||||
console.log(`Skill sources are valid: ${prepared.config.name}`)
|
console.log(`Skill artifact is up to date: ${prepared.config.name}`)
|
||||||
} else {
|
}
|
||||||
replaceDirectory(stagedDir, prepared.outputDir)
|
} else {
|
||||||
|
replaceDirectory(temporaryRoot, outputRoot)
|
||||||
|
for (const prepared of preparedConfigs) {
|
||||||
console.log(`Built skill: ${path.relative(process.cwd(), prepared.outputDir)}`)
|
console.log(`Built skill: ${path.relative(process.cwd(), prepared.outputDir)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,9 +18,9 @@ function documents(language) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const englishDocumentation = [
|
const englishDocumentation = [
|
||||||
{ from: '../../README.md', to: 'references/README.md' },
|
{ from: '../../../README.md', to: 'references/README.md' },
|
||||||
{
|
{
|
||||||
fromDirectory: '../../docs/en',
|
fromDirectory: '../../../docs/en',
|
||||||
toDirectory: 'references/docs/en',
|
toDirectory: 'references/docs/en',
|
||||||
extensions: ['.md'],
|
extensions: ['.md'],
|
||||||
exclude: [
|
exclude: [
|
||||||
@@ -32,9 +32,9 @@ const englishDocumentation = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const russianDocumentation = [
|
const russianDocumentation = [
|
||||||
{ from: '../../README_RU.md', to: 'references/README_RU.md' },
|
{ from: '../../../README_RU.md', to: 'references/README_RU.md' },
|
||||||
{
|
{
|
||||||
fromDirectory: '../../docs/ru',
|
fromDirectory: '../../../docs/ru',
|
||||||
toDirectory: 'references/docs/ru',
|
toDirectory: 'references/docs/ru',
|
||||||
extensions: ['.md'],
|
extensions: ['.md'],
|
||||||
exclude: [
|
exclude: [
|
||||||
@@ -49,7 +49,7 @@ export default [
|
|||||||
{
|
{
|
||||||
name: 'svg-sprites',
|
name: 'svg-sprites',
|
||||||
description: 'Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes for standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit, or Alpine.js, SpriteConfig.input, --input, SpriteViewer, or --icon-color-N. Do NOT use for custom SVG sprites, favicons, raster images, icon fonts, choosing an icon set, or inline SVG without this package.',
|
description: 'Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes for standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit, or Alpine.js, SpriteConfig.input, --input, SpriteViewer, or --icon-color-N. Do NOT use for custom SVG sprites, favicons, raster images, icon fonts, choosing an icon set, or inline SVG without this package.',
|
||||||
output: '../artifacts/svg-sprites',
|
output: 'svg-sprites',
|
||||||
maxSkillBytes: 48_000,
|
maxSkillBytes: 48_000,
|
||||||
documents: documents('en'),
|
documents: documents('en'),
|
||||||
copy: englishDocumentation,
|
copy: englishDocumentation,
|
||||||
@@ -57,7 +57,7 @@ export default [
|
|||||||
{
|
{
|
||||||
name: 'svg-sprites-ru',
|
name: 'svg-sprites-ru',
|
||||||
description: 'Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок.',
|
description: 'Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок.',
|
||||||
output: '../artifacts/svg-sprites-ru',
|
output: 'svg-sprites-ru',
|
||||||
maxSkillBytes: 48_000,
|
maxSkillBytes: 48_000,
|
||||||
documents: documents('ru'),
|
documents: documents('ru'),
|
||||||
copy: russianDocumentation,
|
copy: russianDocumentation,
|
||||||
176
src/skills/svg-sprites/src/en/references/complex-svg.md
Normal file
176
src/skills/svg-sprites/src/en/references/complex-svg.md
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
# Complex SVGs: diagnostics and safe generation
|
||||||
|
|
||||||
|
## When to use this reference
|
||||||
|
|
||||||
|
Use this document when a source contains `<defs>`, gradients, patterns, filters, masks, clip paths, internal `<style>`/classes, `url(#id)`, CSS variables, `<use>`, text, an unusual `viewBox`, spaces in its filename, or changes visually after generation. Also use it for reports involving color, sizing, clipping, or fragment-ID collisions.
|
||||||
|
|
||||||
|
## Classify the risk first
|
||||||
|
|
||||||
|
Inspect the source SVG before editing it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sprite:file-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the actual package script for the sprite. Then compare the source with `.svg-sprite/sprite.svg` and the manifest; do not draw conclusions from a successful exit code alone.
|
||||||
|
|
||||||
|
Pay particular attention to:
|
||||||
|
|
||||||
|
- `fill="url(#gradient)"`, `stroke="url(#pattern)"`;
|
||||||
|
- `filter="url(#shadow)"`, `mask="url(#mask)"`, `clip-path="url(#clip)"`;
|
||||||
|
- CSS rules inside `<style>` and external stylesheets;
|
||||||
|
- colors expressed through classes, presentation attributes, and inline `style` at the same time;
|
||||||
|
- `currentColor`, existing `var(...)`, `context-fill`, and `context-stroke`;
|
||||||
|
- duplicate IDs in `<defs>` across different files;
|
||||||
|
- SVGs without a `viewBox`, or with width/height that does not match the viewBox;
|
||||||
|
- embedded images, fonts, scripts, or external references.
|
||||||
|
|
||||||
|
## Actual pipeline
|
||||||
|
|
||||||
|
The compiler first applies SVGO `preset-default` while preserving `viewBox`, then applies custom transforms in this order:
|
||||||
|
|
||||||
|
1. `removeSize` removes `width` and `height` from the root `<svg>`.
|
||||||
|
2. `replaceColors` collects `fill` and `stroke` values from attributes and inline `style`, then replaces them with `var(--icon-color-N, fallback)`.
|
||||||
|
3. `addTransition` adds inline color transitions to `path`, `circle`, `ellipse`, `rect`, `line`, `polyline`, `polygon`, `text`, `tspan`, and `use` elements.
|
||||||
|
|
||||||
|
All three options default to `true` and apply to the entire sprite, not to individual icons.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'illustrations',
|
||||||
|
transform: {
|
||||||
|
removeSize: false,
|
||||||
|
replaceColors: false,
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a config for one of potentially many sprite modules in a project; its directory does not have to match a module/feature directory. For Next, use the corresponding full `mode` with the same `transform`.
|
||||||
|
|
||||||
|
## Dimensions and viewBox
|
||||||
|
|
||||||
|
`removeSize: true` removes intrinsic `width`/`height`, but does not create a missing `viewBox`. If the source lacks a valid `viewBox`, the generated icon may scale incorrectly or have a zero-sized viewport.
|
||||||
|
|
||||||
|
Correct source preparation:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="..." />
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
If physical dimensions are part of an illustration's contract, set `removeSize: false` and verify component-prop behavior. Do not preserve width/height as a substitute for a missing viewBox.
|
||||||
|
|
||||||
|
React compilation leaves the root sprite `rootViewBox` disabled; Next enables it. Every shape must still have its own valid viewBox, which is included in the manifest and used by the Viewer.
|
||||||
|
|
||||||
|
## Colors
|
||||||
|
|
||||||
|
For one detected color, the fallback becomes `currentColor`:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
stroke="var(--icon-color-1, currentColor)"
|
||||||
|
```
|
||||||
|
|
||||||
|
For multiple colors, the original fallbacks are preserved:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
fill="var(--icon-color-1, #798198)"
|
||||||
|
fill="var(--icon-color-2, #ffffff)"
|
||||||
|
```
|
||||||
|
|
||||||
|
The values `none`, `transparent`, `inherit`, `unset`, and `initial` are not replaced. Color comparison normalizes case and whitespace but does not merge equivalent forms such as `#fff`, `#ffffff`, and `rgb(...)`.
|
||||||
|
|
||||||
|
Automatic analysis is primarily reliable for `fill`/`stroke` attributes and inline `style`. It does not parse CSS selectors in an internal `<style>` or external stylesheet as a full CSS AST.
|
||||||
|
|
||||||
|
For `url(#...)`, existing nested `var(...)`, gradients, and patterns, automatic replacement requires inspection of the generated output. If a paint-server reference changed or the Viewer shows incorrect controls, disable `replaceColors` for the entire sprite:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
transform: {
|
||||||
|
replaceColors: false,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If ordinary recolorable icons are also needed, move complex illustrations into a separate sprite with a separate config. This is preferable to manually editing the generated SVG.
|
||||||
|
|
||||||
|
`addTransition` is independent of `replaceColors`. Even when original colors are preserved, transitions may still be added. For filters, animations, or custom CSS, disable both options if an inline transition changes behavior.
|
||||||
|
|
||||||
|
## Defs, references, and IDs
|
||||||
|
|
||||||
|
After SVGO and compilation, verify that each `url(#id)` or `<use href="#id">` refers to an existing ID within the corresponding shape. Do not assume IDs remain literal copies of the source; the optimizer/compiler may change them.
|
||||||
|
|
||||||
|
At minimum, check that:
|
||||||
|
|
||||||
|
- each gradient/pattern applies to the intended path;
|
||||||
|
- the filter region does not clip blur/shadow;
|
||||||
|
- masks and clip paths preserve their coordinate system (`userSpaceOnUse`/`objectBoundingBox`);
|
||||||
|
- an internal `<use>` is not confused with the sprite's external fragment;
|
||||||
|
- equal IDs from different source SVGs do not cause cross-icon collisions in the final document;
|
||||||
|
- external file/URL references are permitted by the production CSP and deployment.
|
||||||
|
|
||||||
|
If IDs collide, first make the source IDs unique and update all references within the SVG. Do not edit the compiled sprite.
|
||||||
|
|
||||||
|
## Filenames and external fragments
|
||||||
|
|
||||||
|
`FileManagerIcon` in the examples below is only an example generated name for a separate config with `name: 'file-manager'`; it is not a fixed API name.
|
||||||
|
|
||||||
|
A safe basename matches:
|
||||||
|
|
||||||
|
```text
|
||||||
|
^[a-zA-Z][a-zA-Z0-9_-]*$
|
||||||
|
```
|
||||||
|
|
||||||
|
It is preserved as the fragment ID. Other names, such as `folder open.svg` or `24-check.svg`, remain public TypeScript `icon` values but receive a stable `icon-<16 hex>` ID.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon icon="folder open" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not manually construct `#folder open`. Use the generated component or `.svg-sprite/svg-sprite.manifest.js`, which records both `name` and the actual `id`.
|
||||||
|
|
||||||
|
Different files with the same basename are forbidden, even from different directories. Rename one source meaningfully; source order or overlap never selects a winner.
|
||||||
|
|
||||||
|
## Rendering method
|
||||||
|
|
||||||
|
To control `color` and `--icon-color-N`, use the generated React component or `<svg><use>`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon
|
||||||
|
icon="diagram"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#334155',
|
||||||
|
'--icon-color-2': '#38bdf8',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated style type accepts `--icon-color-${number}`. `<img>` and CSS `background-image` load the SVG as an isolated document, so page variables do not propagate into it. A CSS mask keeps only the silhouette and loses gradients, filters, and color differences.
|
||||||
|
|
||||||
|
External stack-fragment support and paint-server behavior can vary across browsers. For critical complex graphics, when diagnosing runtime behavior and browser tools are available, test the target browsers; if they are incompatible, an SVG sprite may be the wrong delivery mechanism for that illustration.
|
||||||
|
|
||||||
|
## Required verification
|
||||||
|
|
||||||
|
1. Run generation with the correct mode.
|
||||||
|
2. Run the project's typecheck.
|
||||||
|
3. Open the generated sprite and find the shape using the ID from the manifest.
|
||||||
|
4. Statically compare `viewBox`, IDs, `url(#...)`, colors, and inline styles.
|
||||||
|
5. If the target/pipeline changed or a runtime issue is being diagnosed, build the production bundle and inspect the external hashed SVG.
|
||||||
|
6. When SpriteViewer and visual tools are available, test default colors and each `--icon-color-N` separately.
|
||||||
|
7. When browser tools are available and the runtime risk warrants it, test SSR/hydration for Next.js and target browsers for external fragments.
|
||||||
|
8. Do not claim visual or accessibility equivalence between source and output without the necessary tools and an actual comparison.
|
||||||
|
|
||||||
|
## Common symptoms and actions
|
||||||
|
|
||||||
|
- Icon became entirely `currentColor`: the pipeline detected one color. If the source semantics are more complex, disable `replaceColors` or normalize the source attributes.
|
||||||
|
- Gradient disappeared: check whether `fill="url(#...)"` was transformed, whether the target ID exists, and whether it collides with another icon.
|
||||||
|
- Shadow is clipped: inspect the filter region and viewBox; `removeSize` does not expand the area by itself.
|
||||||
|
- Viewer has no color controls: the color is defined through a class/stylesheet, or `replaceColors: false`; this is expected.
|
||||||
|
- Transition is duplicated or interferes with animation: an existing inline `transition` is not overwritten, but generated CSS also adds transitions; disable `addTransition` for the sprite.
|
||||||
|
- `<img>` ignores variables: switch to `<svg><use>` or the generated component; page variables cannot be passed into an isolated SVG document.
|
||||||
|
- A manual fragment fails for a name containing spaces: use the ID from the manifest.
|
||||||
|
- One complex icon requires different transforms: move it to a separate sprite; per-icon transform config is not supported.
|
||||||
|
|
||||||
|
For mode-specific execution and verification, return to the exact-mode guide selected from the main `SKILL.md`.
|
||||||
176
src/skills/svg-sprites/src/ru/references/complex-svg.md
Normal file
176
src/skills/svg-sprites/src/ru/references/complex-svg.md
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
# Сложные SVG: диагностика и безопасная генерация
|
||||||
|
|
||||||
|
## Когда открывать
|
||||||
|
|
||||||
|
Открывай этот документ, если исходник содержит `<defs>`, gradients, patterns, filters, masks, clip paths, внутренние `<style>`/classes, `url(#id)`, CSS variables, `<use>`, text, нестандартный `viewBox`, пробелы в имени файла или визуально меняется после генерации. Также открывай его при жалобах на цвет, размер, обрезание или конфликт fragment ID.
|
||||||
|
|
||||||
|
## Сначала классифицируй риск
|
||||||
|
|
||||||
|
Проверь исходный SVG до редактирования:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sprite:file-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
Используй фактический package script нужного спрайта. Затем сравни source с `.svg-sprite/sprite.svg` и manifest, не делая вывод только по успешному exit code.
|
||||||
|
|
||||||
|
Особого внимания требуют:
|
||||||
|
|
||||||
|
- `fill="url(#gradient)"`, `stroke="url(#pattern)"`;
|
||||||
|
- `filter="url(#shadow)"`, `mask="url(#mask)"`, `clip-path="url(#clip)"`;
|
||||||
|
- CSS rules внутри `<style>` и внешние stylesheets;
|
||||||
|
- цвета через classes, presentation attributes и inline `style` одновременно;
|
||||||
|
- `currentColor`, уже существующие `var(...)`, `context-fill` и `context-stroke`;
|
||||||
|
- повторяющиеся IDs в `<defs>` разных файлов;
|
||||||
|
- SVG без `viewBox` или с width/height, не соответствующими viewBox;
|
||||||
|
- embedded images, fonts, scripts или external references.
|
||||||
|
|
||||||
|
## Фактический pipeline
|
||||||
|
|
||||||
|
Компилятор сначала применяет SVGO `preset-default`, сохраняя `viewBox`, затем custom transforms в таком порядке:
|
||||||
|
|
||||||
|
1. `removeSize` удаляет `width` и `height` с корневого `<svg>`.
|
||||||
|
2. `replaceColors` собирает значения `fill` и `stroke` из attributes и inline `style`, затем заменяет их на `var(--icon-color-N, fallback)`.
|
||||||
|
3. `addTransition` добавляет inline transition цветным `path`, `circle`, `ellipse`, `rect`, `line`, `polyline`, `polygon`, `text`, `tspan` и `use`.
|
||||||
|
|
||||||
|
Все три опции по умолчанию `true` и применяются ко всему спрайту, не к отдельной иконке.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||||
|
|
||||||
|
export default defineSpriteConfig({
|
||||||
|
mode: 'react@vite',
|
||||||
|
name: 'illustrations',
|
||||||
|
transform: {
|
||||||
|
removeSize: false,
|
||||||
|
replaceColors: false,
|
||||||
|
addTransition: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Это config для одного из потенциально многих sprite-модулей; его каталог не обязан совпадать с module/feature-каталогом. Для Next укажи соответствующий полный `mode` с тем же `transform`.
|
||||||
|
|
||||||
|
## Размеры и viewBox
|
||||||
|
|
||||||
|
`removeSize: true` удаляет intrinsic `width`/`height`, но не создаёт отсутствующий `viewBox`. Если source не имеет корректного `viewBox`, generated icon может получить неверное масштабирование или нулевую область просмотра.
|
||||||
|
|
||||||
|
Правильная подготовка source:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="..." />
|
||||||
|
</svg>
|
||||||
|
```
|
||||||
|
|
||||||
|
Если физические размеры являются частью контракта иллюстрации, установи `removeSize: false` и проверь поведение component props. Не используй сохранение width/height как замену отсутствующему viewBox.
|
||||||
|
|
||||||
|
React compile оставляет root sprite `rootViewBox` выключенным; Next включает его. У каждой shape всё равно должен быть собственный корректный viewBox, который попадает в manifest и используется Viewer.
|
||||||
|
|
||||||
|
## Цвета
|
||||||
|
|
||||||
|
Для одного обнаруженного цвета fallback становится `currentColor`:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
stroke="var(--icon-color-1, currentColor)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Для нескольких цветов сохраняются исходные fallbacks:
|
||||||
|
|
||||||
|
```svg
|
||||||
|
fill="var(--icon-color-1, #798198)"
|
||||||
|
fill="var(--icon-color-2, #ffffff)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Значения `none`, `transparent`, `inherit`, `unset` и `initial` не заменяются. Сравнение цветов нормализует регистр и пробелы, но не приводит эквивалентные формы (`#fff`, `#ffffff`, `rgb(...)`) к одному цвету.
|
||||||
|
|
||||||
|
Автоматический анализ надёжен прежде всего для `fill`/`stroke` attributes и inline `style`. Он не разбирает CSS selectors во внутреннем `<style>` и внешний stylesheet как полноценный CSS AST.
|
||||||
|
|
||||||
|
Для `url(#...)`, уже вложенных `var(...)`, gradients и patterns автоматическая замена требует проверки generated output. Если ссылка на paint server изменилась или Viewer неверно показывает controls, отключи `replaceColors` для всего этого спрайта:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
transform: {
|
||||||
|
replaceColors: false,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Если рядом нужны обычные recolorable icons, вынеси сложные иллюстрации в отдельный sprite с отдельным config. Это предпочтительнее ручной правки generated SVG.
|
||||||
|
|
||||||
|
`addTransition` независим от `replaceColors`. При сохранении исходных цветов transition всё равно может добавиться. Для filters, анимаций или собственного CSS отключай обе опции, если inline transition меняет поведение.
|
||||||
|
|
||||||
|
## Defs, references и IDs
|
||||||
|
|
||||||
|
После SVGO и сборки проверь, что каждая ссылка `url(#id)` или `<use href="#id">` указывает на реально существующий ID внутри соответствующей shape. Не предполагай, что IDs останутся буквальной копией source: optimizer/compiler может их изменить.
|
||||||
|
|
||||||
|
Проверяй как минимум:
|
||||||
|
|
||||||
|
- gradient/pattern применяется к нужному path;
|
||||||
|
- filter region не обрезает blur/shadow;
|
||||||
|
- mask и clipPath сохраняют coordinate system (`userSpaceOnUse`/`objectBoundingBox`);
|
||||||
|
- internal `<use>` не спутан с внешним fragment спрайта;
|
||||||
|
- одинаковые IDs из разных source SVG не создают cross-icon collision в итоговом документе;
|
||||||
|
- external file/URL references допустимы в production CSP и deployment.
|
||||||
|
|
||||||
|
Если IDs конфликтуют, сначала сделай source IDs уникальными и обнови все ссылки внутри SVG. Не правь compiled sprite.
|
||||||
|
|
||||||
|
## Имена файлов и внешний fragment
|
||||||
|
|
||||||
|
`FileManagerIcon` в примерах ниже — только пример generated-имени для отдельного config с `name: 'file-manager'`; это не фиксированное имя API.
|
||||||
|
|
||||||
|
Безопасный basename соответствует:
|
||||||
|
|
||||||
|
```text
|
||||||
|
^[a-zA-Z][a-zA-Z0-9_-]*$
|
||||||
|
```
|
||||||
|
|
||||||
|
Он сохраняется как fragment ID. Остальные имена, например `folder open.svg` или `24-check.svg`, остаются публичными значениями TypeScript `icon`, но получают стабильный ID `icon-<16 hex>`.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon icon="folder open" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Не создавай вручную `#folder open`. Используй generated component либо `.svg-sprite/svg-sprite.manifest.js`, где записаны `name` и фактический `id`.
|
||||||
|
|
||||||
|
Разные файлы с одинаковым basename запрещены даже из разных directories. Переименуй один source осмысленно; порядок или пересечение источников не выбирают победителя.
|
||||||
|
|
||||||
|
## Способ отображения
|
||||||
|
|
||||||
|
Для управления `color` и `--icon-color-N` используй generated React-компонент или `<svg><use>`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<FileManagerIcon
|
||||||
|
icon="diagram"
|
||||||
|
style={{
|
||||||
|
'--icon-color-1': '#334155',
|
||||||
|
'--icon-color-2': '#38bdf8',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Generated style type допускает `--icon-color-${number}`. `<img>` и CSS `background-image` загружают SVG как изолированный document, поэтому variables страницы внутрь не передаются. CSS mask оставляет только силуэт и теряет gradients, filters и различия цветов.
|
||||||
|
|
||||||
|
External stack fragment support и поведение paint servers могут различаться между browsers. Для критичной сложной графики при диагностике runtime и наличии browser-инструментов проверь целевые browsers; при несовместимости SVG sprite может быть неподходящим способом доставки именно этой иллюстрации.
|
||||||
|
|
||||||
|
## Обязательная проверка
|
||||||
|
|
||||||
|
1. Запусти генерацию с правильным mode.
|
||||||
|
2. Запусти typecheck проекта.
|
||||||
|
3. Открой generated sprite и найди shape по ID из manifest.
|
||||||
|
4. Статически сверь `viewBox`, IDs, `url(#...)`, colors и inline styles.
|
||||||
|
5. Если менялись target/pipeline или диагностируется runtime, собери production bundle и проверь внешний hashed SVG.
|
||||||
|
6. При наличии SpriteViewer и визуальных инструментов проверь default colors и каждую `--icon-color-N` отдельно.
|
||||||
|
7. При наличии browser-инструментов и соответствующем runtime-риске проверь SSR/hydration для Next.js и целевые browsers для external fragments.
|
||||||
|
8. Не утверждай визуальную или a11y эквивалентность source и результата без доступных инструментов и фактического сравнения.
|
||||||
|
|
||||||
|
## Типовые симптомы и действия
|
||||||
|
|
||||||
|
- Иконка стала полностью `currentColor`: pipeline увидел один цвет. Если исходная семантика сложнее, отключи `replaceColors` или нормализуй source attributes.
|
||||||
|
- Gradient исчез: проверь, не преобразован ли `fill="url(#...)"`, существует ли target ID и не конфликтует ли он с другим icon.
|
||||||
|
- Shadow обрезан: проверь filter region и viewBox; `removeSize` сам по себе не расширяет область.
|
||||||
|
- Цветовые controls Viewer отсутствуют: цвет задан через class/stylesheet либо `replaceColors: false`; это ожидаемо.
|
||||||
|
- Transition дублируется или мешает animation: существующий inline `transition` не перезаписывается, но generated CSS также добавляет transitions; отключи `addTransition` для sprite.
|
||||||
|
- `<img>` игнорирует variables: смени rendering на `<svg><use>`/generated component, не пытайся передать page variables в изолированный SVG.
|
||||||
|
- Ручной fragment не работает для имени с пробелом: используй ID из manifest.
|
||||||
|
- Один сложный icon требует иных transforms: вынеси его в отдельный sprite; per-icon transform config отсутствует.
|
||||||
|
|
||||||
|
Для mode-specific запуска и проверки вернись к exact-mode guide, выбранному в основном `SKILL.md`.
|
||||||
Reference in New Issue
Block a user