mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-07-22 04:40:17 +03:00
docs: обновить документацию generated-контракта
- описаны единая конфигурация и exact modes - обновлена структура .svg-sprite - удалены материалы legacy pipeline - синхронизированы русская и английская версии skill
This commit is contained in:
@@ -1,102 +0,0 @@
|
||||
# Legacy mode
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
A quick guide to generating centralized SVG sprites in `symbol` and `stack` formats, with an optional HTML preview.
|
||||
|
||||
## 1. Install the package
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## 2. Prepare the icons and config
|
||||
|
||||
```text
|
||||
project/
|
||||
├── src/assets/icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
└── svg-sprites.config.ts
|
||||
```
|
||||
|
||||
```ts
|
||||
// svg-sprites.config.ts
|
||||
import { defineLegacyConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineLegacyConfig({
|
||||
output: 'public/sprites',
|
||||
preview: true,
|
||||
sprites: [
|
||||
{
|
||||
name: 'icons',
|
||||
input: 'src/assets/icons',
|
||||
format: 'symbol',
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## 3. Add generation
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "svg-sprites --mode legacy .",
|
||||
"prebuild": "npm run sprites"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run the local package through the script:
|
||||
|
||||
```bash
|
||||
npm run sprites
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```text
|
||||
public/sprites/
|
||||
├── icons.sprite.svg
|
||||
└── preview.html
|
||||
```
|
||||
|
||||
With `preview: false`, the HTML file is not created. For the `stack` format, specify `format: 'stack'`.
|
||||
|
||||
## 4. Use the symbol sprite
|
||||
|
||||
```html
|
||||
<svg width="24" height="24" aria-label="Done">
|
||||
<use href="/sprites/icons.sprite.svg#check"></use>
|
||||
</svg>
|
||||
```
|
||||
|
||||
## Multiple sprites
|
||||
|
||||
Add multiple entries to `sprites`:
|
||||
|
||||
```ts
|
||||
sprites: [
|
||||
{
|
||||
name: 'icons',
|
||||
input: 'src/assets/icons',
|
||||
format: 'symbol',
|
||||
},
|
||||
{
|
||||
name: 'logos',
|
||||
input: 'src/assets/logos',
|
||||
format: 'stack',
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
All output files and the shared `preview.html` will be written to `output`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Config not found: make sure `svg-sprites.config.ts` is located in the specified root directory.
|
||||
- No icons: check `sprites[].input` and the `.svg` extension.
|
||||
- Preview not needed: set `preview: false`.
|
||||
|
||||
For programmatic use, see [`generateLegacy`](programmatic-api.md#generatelegacy).
|
||||
@@ -1,122 +0,0 @@
|
||||
# Migrating from 0.1.x to 1.0
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
Version 1.0 separates local generation for React and Next.js from the centralized legacy mode. The old config cannot be mixed with the new API in a single CLI invocation.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the package as a development dependency so the migration uses the version recorded in the project lockfile:
|
||||
|
||||
```bash
|
||||
npm install --save-dev @gromlab/svg-sprites
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
The CLI now always requires an explicit `--mode` and a path to the configuration directory:
|
||||
|
||||
```text
|
||||
"sprites": "svg-sprites"
|
||||
→ "sprites": "svg-sprites --mode <mode> <path>"
|
||||
```
|
||||
|
||||
Choose a mode based on your environment:
|
||||
|
||||
| Environment | Mode |
|
||||
|---|---|
|
||||
| React + Vite | `react@vite` |
|
||||
| React + Webpack 5 | `react@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` |
|
||||
| Centralized legacy setup | `legacy` |
|
||||
|
||||
## React and Next.js
|
||||
|
||||
Instead of a root-level `svg-sprites.config.ts`, create a local `svg-sprite.config.ts` next to the icon set:
|
||||
|
||||
```ts
|
||||
import { defineNextSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineNextSpriteConfig({
|
||||
name: 'global',
|
||||
inputFolder: './icons',
|
||||
})
|
||||
```
|
||||
|
||||
For regular React, use `defineReactSpriteConfig`. A folder and an explicit list of shared SVG files can be combined using `inputFolder` and `inputFiles`.
|
||||
|
||||
Add the local CLI with the selected mode to `package.json`, for example:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:global": "svg-sprites --mode next@app/turbopack src/ui/global/svg-sprite"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run it with `npm run sprite:global` before importing the generated component.
|
||||
|
||||
The old `publicPath` and `react` options are no longer needed. The generated module is created next to the config and adds its own `.gitignore`, while Vite, Webpack, or Next.js emits the SVG as a separate asset with a content hash.
|
||||
|
||||
The `<SvgSprite icon="..." />` component is replaced by a component whose name is derived from `name`:
|
||||
|
||||
```tsx
|
||||
<GlobalIcon icon="check" />
|
||||
```
|
||||
|
||||
To browse the icons, add `<SpriteViewer>` as a debug page in the application. A separate `preview.html` is available only in legacy mode.
|
||||
|
||||
## Legacy mode
|
||||
|
||||
If you need to preserve the centralized structure, rename the helper and the format fields:
|
||||
|
||||
```ts
|
||||
import { defineLegacyConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineLegacyConfig({
|
||||
output: 'public/sprites',
|
||||
preview: true,
|
||||
sprites: [
|
||||
{
|
||||
name: 'icons',
|
||||
input: 'src/assets/icons',
|
||||
format: 'stack',
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
- `defineConfig` has been replaced with `defineLegacyConfig`;
|
||||
- `sprites[].mode` has been renamed to `sprites[].format`;
|
||||
- `generate` has been replaced with `generateLegacy`;
|
||||
- `loadConfig` has been replaced with `loadLegacyConfig`;
|
||||
- `publicPath` and generation of the old shared React component have been removed.
|
||||
|
||||
Add the local CLI to `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "svg-sprites --mode legacy ."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run it with `npm run sprites`.
|
||||
|
||||
## Programmatic API
|
||||
|
||||
The package is distributed as ESM only. Replace `require()` with `import`.
|
||||
|
||||
`compileSpriteContent` now returns `Promise<Uint8Array>` so that the public declarations do not require `@types/node` to be installed. In Node.js, the actual result is compatible with APIs that accept `Uint8Array`.
|
||||
|
||||
## After migration
|
||||
|
||||
1. Add an explicit generation command before `dev`, `build`, and `typecheck`.
|
||||
2. Generate the new output and run type checking while the old artifacts are still available.
|
||||
3. Replace imports and verify the icons and color variables using `SpriteViewer` or the legacy `preview.html`.
|
||||
4. Only then remove confirmed old generated files and obsolete ignore rules without deleting source SVGs.
|
||||
@@ -22,19 +22,28 @@ src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineNextSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineNextSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## 3. Add generation
|
||||
|
||||
For Turbopack:
|
||||
@@ -42,7 +51,7 @@ For Turbopack:
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites --mode next@app/turbopack src/ui/file-manager/svg-sprite",
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager"
|
||||
}
|
||||
@@ -85,7 +94,7 @@ The viewer is interactive, so it requires a separate Client Component boundary:
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('@/ui/file-manager/svg-sprite/manifest'),
|
||||
() => import('@/ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function SpritesPage() {
|
||||
|
||||
@@ -22,25 +22,34 @@ src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineNextSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineNextSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@pages/webpack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## 3. Add generation
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites --mode next@pages/webpack src/ui/file-manager/svg-sprite",
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager"
|
||||
}
|
||||
@@ -77,7 +86,7 @@ The component works the same way with SSR, SSG, and client-side navigation. Next
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('@/ui/file-manager/svg-sprite/manifest'),
|
||||
() => import('@/ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export default function SpritesPage() {
|
||||
|
||||
@@ -2,100 +2,65 @@
|
||||
|
||||
[← Back to home](../../README.md)
|
||||
|
||||
The package provides a main Node.js entry point and a separate React runtime entry point. Both are distributed as ESM only and must be loaded with `import`.
|
||||
The package is ESM-only and provides one Node.js generation API. The React runtime with `SpriteViewer` is available from the separate `@gromlab/svg-sprites/react` entry point.
|
||||
|
||||
To resolve `@gromlab/svg-sprites/react` in TypeScript, use `moduleResolution: "bundler"`, `"node16"`, or `"nodenext"`.
|
||||
|
||||
## Main entry point
|
||||
## `generateSprite`
|
||||
|
||||
```ts
|
||||
import {
|
||||
defineNextSpriteConfig,
|
||||
defineReactSpriteConfig,
|
||||
generateNextSprite,
|
||||
generateReactSprite,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
import { generateSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
The main entry point does not import React and can be used in CLIs, build scripts, and Node.js tools.
|
||||
|
||||
## `generateReactSprite`
|
||||
|
||||
```ts
|
||||
import { generateReactSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
const result = await generateReactSprite(
|
||||
'src/ui/file-manager/svg-sprite',
|
||||
'vite',
|
||||
const result = await generateSprite(
|
||||
'src/ui/file-manager/svg-sprite/svg-sprite.config.ts',
|
||||
)
|
||||
```
|
||||
|
||||
The second argument is required:
|
||||
The first argument accepts the full 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
|
||||
type ReactAssetTarget = 'vite' | 'webpack'
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```ts
|
||||
type ReactSpriteGenerationResult = {
|
||||
name: string
|
||||
rootDir: string
|
||||
generatedDir: string
|
||||
spritePath: string
|
||||
manifestPath: string
|
||||
iconCount: number
|
||||
target: 'vite' | 'webpack'
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
console.log(result.name)
|
||||
console.log(result.iconCount)
|
||||
console.log(result.spritePath)
|
||||
console.log(result.manifestPath)
|
||||
```
|
||||
|
||||
The function loads `svg-sprite.config.ts` from the specified root, compiles the SVG files, and safely updates managed files.
|
||||
|
||||
## `generateNextSprite`
|
||||
|
||||
```ts
|
||||
import { generateNextSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
const result = await generateNextSprite(
|
||||
'src/ui/file-manager/svg-sprite',
|
||||
{
|
||||
router: 'app',
|
||||
bundler: 'turbopack',
|
||||
await generateSprite('src/ui/file-manager/svg-sprite/custom-config.json', {
|
||||
mode: 'react@webpack',
|
||||
name: 'documents',
|
||||
inputFolder: './assets',
|
||||
inputFiles: ['../../shared/search.svg'],
|
||||
transform: {
|
||||
addTransition: false,
|
||||
},
|
||||
)
|
||||
generatedNotice: false,
|
||||
})
|
||||
```
|
||||
|
||||
Available values:
|
||||
Configuration is resolved in this order:
|
||||
|
||||
```ts
|
||||
type NextSpriteGenerationOptions = {
|
||||
router: 'app' | 'pages'
|
||||
bundler: 'turbopack' | 'webpack'
|
||||
}
|
||||
```text
|
||||
defaults → config → API overrides
|
||||
```
|
||||
|
||||
The result also contains the selected `router`, `bundler`, and the full target in the form `next@app/turbopack`.
|
||||
|
||||
## `defineReactSpriteConfig`
|
||||
For fully programmatic generation, pass a directory and provide the required settings as overrides:
|
||||
|
||||
```ts
|
||||
import { defineReactSpriteConfig } from '@gromlab/svg-sprites'
|
||||
await generateSprite('src/ui/file-manager/svg-sprite', {
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
inputFiles: [
|
||||
'../../shared/search.svg',
|
||||
'../../shared/settings.svg',
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
export default defineReactSpriteConfig({
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
inputFolder: './icons',
|
||||
inputFiles: [
|
||||
'../../shared/icons/check.svg',
|
||||
],
|
||||
inputFiles: ['../../shared/check.svg'],
|
||||
transform: {
|
||||
removeSize: true,
|
||||
replaceColors: true,
|
||||
@@ -105,99 +70,54 @@ export default defineReactSpriteConfig({
|
||||
})
|
||||
```
|
||||
|
||||
`inputFolder` and `inputFiles` are combined. The helper returns the configuration without runtime transformations and provides TypeScript autocomplete.
|
||||
`defineSpriteConfig` is an identity helper for TypeScript autocomplete. JavaScript can export the same object with `export default`, while JSON contains the object directly.
|
||||
|
||||
## `defineNextSpriteConfig`
|
||||
## Specialized wrappers
|
||||
|
||||
The specialized functions are available as wrappers around `generateSprite`:
|
||||
|
||||
```ts
|
||||
import { defineNextSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { generateNextSprite, generateReactSprite } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineNextSpriteConfig({
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
inputFolder: './icons',
|
||||
await generateReactSprite('path/to/config.ts', 'vite')
|
||||
await generateNextSprite('path/to/config.ts', {
|
||||
router: 'app',
|
||||
bundler: 'turbopack',
|
||||
})
|
||||
```
|
||||
|
||||
Next.js uses the same configuration contract as the React presets.
|
||||
An explicitly supplied target overrides `mode` from the file. Prefer `generateSprite` in new code.
|
||||
|
||||
## `generateLegacy`
|
||||
## Config API
|
||||
|
||||
```ts
|
||||
import { generateLegacy } from '@gromlab/svg-sprites'
|
||||
|
||||
const results = await generateLegacy({
|
||||
output: 'public/sprites',
|
||||
preview: false,
|
||||
sprites: [
|
||||
{
|
||||
name: 'icons',
|
||||
input: 'src/assets/icons',
|
||||
format: 'symbol',
|
||||
},
|
||||
],
|
||||
})
|
||||
import {
|
||||
loadSpriteConfig,
|
||||
resolveSpriteConfig,
|
||||
validateSpriteConfig,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
Returns an array:
|
||||
- `loadSpriteConfig(file)` loads an explicitly selected `.ts`, `.js`, or `.json` file.
|
||||
- `validateSpriteConfig(value)` performs runtime validation.
|
||||
- `resolveSpriteConfig(root, config, overrides)` merges values, applies defaults, and resolves paths relative to `root`.
|
||||
|
||||
```ts
|
||||
type SpriteResult = {
|
||||
name: string
|
||||
format: 'symbol' | 'stack'
|
||||
spritePath: string
|
||||
iconCount: number
|
||||
}
|
||||
```
|
||||
|
||||
For details, see [Legacy mode](legacy.md).
|
||||
|
||||
## Low-level functions
|
||||
|
||||
The main entry point also exports:
|
||||
## Low-level compiler
|
||||
|
||||
```ts
|
||||
import {
|
||||
compileSprite,
|
||||
compileSpriteContent,
|
||||
createShapeTransform,
|
||||
generatePreview,
|
||||
loadLegacyConfig,
|
||||
loadReactSpriteConfig,
|
||||
resolveSpriteEntry,
|
||||
resolveSprites,
|
||||
} from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
These functions are intended for custom orchestration built on top of the existing compiler and writer. For standard usage, prefer `generateReactSprite` and `generateLegacy`.
|
||||
These functions are intended for custom orchestration. Standard generation should use `generateSprite`.
|
||||
|
||||
## React runtime entry point
|
||||
## React runtime
|
||||
|
||||
```tsx
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
Types:
|
||||
|
||||
```ts
|
||||
import type {
|
||||
SpriteManifest,
|
||||
SpriteManifestColor,
|
||||
SpriteManifestIcon,
|
||||
SpriteManifestLoader,
|
||||
SpriteManifestModule,
|
||||
SpriteViewerColorTheme,
|
||||
SpriteViewerProps,
|
||||
SpriteViewerSource,
|
||||
SpriteViewerSources,
|
||||
} from '@gromlab/svg-sprites/react'
|
||||
```
|
||||
|
||||
The React entry point contains `'use client'` and is intended for debug tools. Generated production components are imported from the application's local sprite modules, not from the package's React entry point.
|
||||
|
||||
`SpriteViewerProps.colorTheme` accepts `auto | light | dark`. The default is `auto`, which follows `prefers-color-scheme`; to synchronize it with the application theme, pass the computed `light` or `dark` value.
|
||||
|
||||
## Related guides
|
||||
|
||||
- [React + Vite](react-vite.md)
|
||||
- [React + Webpack 5](react-webpack.md)
|
||||
`SpriteViewer` accepts generated manifests, lazy loaders, or an `import.meta.glob` result. This entry point contains `'use client'` and is intended for debug tools; production components are imported from local sprite modules.
|
||||
|
||||
@@ -19,6 +19,7 @@ src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
@@ -28,24 +29,32 @@ Place the source SVG files in `icons/`.
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineReactSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineReactSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@vite',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned and explicitly re-exports the generated API:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite.
|
||||
|
||||
The complete list of options is available under [React and Next.js configuration](reference.md#react-and-nextjs-configuration).
|
||||
The complete list of options is available under [Unified configuration](reference.md#unified-configuration).
|
||||
|
||||
## 4. Add generation to package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites --mode react@vite src/ui/file-manager/svg-sprite",
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager",
|
||||
"pretypecheck": "npm run sprite:file-manager"
|
||||
@@ -96,7 +105,7 @@ import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = import.meta.glob<SpriteManifestModule>(
|
||||
'/src/**/svg-sprite/manifest.ts',
|
||||
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||
)
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
@@ -104,13 +113,13 @@ export const IconsDebugPage = () => (
|
||||
)
|
||||
```
|
||||
|
||||
Vite automatically finds the generated `manifest.ts` for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts.
|
||||
Vite automatically finds the generated manifest for each React sprite. The `import.meta.glob` pattern must be a string literal, and generation must run before Vite starts.
|
||||
|
||||
Only include the Viewer on a debug route or in an internal tool.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `index.ts`: run `npm run sprite:file-manager`.
|
||||
- The Viewer cannot find the sprite: check the glob path and make sure `manifest.ts` exists.
|
||||
- Missing `.svg-sprite/index.js`: run `npm run sprite:file-manager`.
|
||||
- The Viewer cannot find the sprite: check the glob path to `.svg-sprite/svg-sprite.manifest.js`.
|
||||
- `Refusing to overwrite a user file` error: there is a user file at a generated path.
|
||||
- The icon does not change color: use `color` or `--icon-color-N`.
|
||||
|
||||
@@ -19,6 +19,7 @@ src/ui/file-manager/svg-sprite/
|
||||
├── icons/
|
||||
│ ├── check.svg
|
||||
│ └── folder.svg
|
||||
├── index.ts
|
||||
└── svg-sprite.config.ts
|
||||
```
|
||||
|
||||
@@ -28,24 +29,32 @@ Place the source SVG files in `icons/`.
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/svg-sprite.config.ts
|
||||
import { defineReactSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineReactSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'react@webpack',
|
||||
name: 'file-manager',
|
||||
description: 'File manager icons',
|
||||
})
|
||||
```
|
||||
|
||||
The root barrel is application-owned and explicitly re-exports the generated API:
|
||||
|
||||
```ts
|
||||
// src/ui/file-manager/svg-sprite/index.ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
By default, SVG files are loaded from `./icons`. You can add shared icons from other directories through `inputFiles`: the directory and file list are combined into a single sprite.
|
||||
|
||||
The complete list of options is available under [React and Next.js configuration](reference.md#react-and-nextjs-configuration).
|
||||
The complete list of options is available under [Unified configuration](reference.md#unified-configuration).
|
||||
|
||||
## 4. Add generation to package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprite:file-manager": "svg-sprites --mode react@webpack src/ui/file-manager/svg-sprite",
|
||||
"sprite:file-manager": "svg-sprites src/ui/file-manager/svg-sprite/svg-sprite.config.ts",
|
||||
"predev": "npm run sprite:file-manager",
|
||||
"prebuild": "npm run sprite:file-manager",
|
||||
"pretypecheck": "npm run sprite:file-manager"
|
||||
@@ -87,7 +96,7 @@ Webpack processes the generated `new URL('./sprite.svg', import.meta.url)` throu
|
||||
|
||||
If the project already uses a custom SVG loader, make sure it does not intercept the generated `sprite.svg` instead of Asset Modules.
|
||||
|
||||
The generated component imports `styles.module.css`, so Webpack must process CSS Modules through `css-loader` and `style-loader` or `MiniCssExtractPlugin`. If the TypeScript project does not include a declaration for CSS Modules, add one separately.
|
||||
The generated component imports `react/react-component.module.css`, so Webpack must process CSS Modules through `css-loader` and `style-loader` or `MiniCssExtractPlugin`. If the TypeScript project does not include a declaration for CSS Modules, add one separately.
|
||||
|
||||
## 6. Add a debug page
|
||||
|
||||
@@ -97,8 +106,8 @@ Webpack does not support Vite's `import.meta.glob` API, so provide static loader
|
||||
import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = [
|
||||
() => import('./ui/file-manager/svg-sprite/manifest'),
|
||||
() => import('./ui/navigation/svg-sprite/manifest'),
|
||||
() => import('./ui/file-manager/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('./ui/navigation/svg-sprite/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
@@ -112,8 +121,8 @@ Only include the Viewer on a debug route or in an internal tool.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `index.ts`: run `npm run sprite:file-manager`.
|
||||
- The Viewer does not load the sprite: check the path in `import()` and make sure `manifest.ts` exists.
|
||||
- Missing `.svg-sprite/index.js`: run `npm run sprite:file-manager`.
|
||||
- The Viewer does not load the sprite: check the `import()` path to `.svg-sprite/svg-sprite.manifest.js`.
|
||||
- Incorrect asset URL: check `output.publicPath`.
|
||||
- Another loader intercepts the SVG: exclude the generated sprite from the incompatible rule.
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ Reference for the configuration, generated API, and behavior of `@gromlab/svg-sp
|
||||
- [Next.js Pages Router](next-pages.md)
|
||||
- [React + Vite](react-vite.md)
|
||||
- [React + Webpack 5](react-webpack.md)
|
||||
- [Native HTML and classic SVG sprites](legacy.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -25,10 +24,10 @@ npm install --save-dev @gromlab/svg-sprites
|
||||
|
||||
## CLI and generation modes
|
||||
|
||||
The CLI accepts one mode and a path to the configuration directory:
|
||||
The CLI accepts exactly one path: an explicitly selected config file or a directory for config-less generation:
|
||||
|
||||
```text
|
||||
svg-sprites --mode <mode> <path>
|
||||
svg-sprites [options] <config-file-or-directory>
|
||||
```
|
||||
|
||||
| Environment | Mode |
|
||||
@@ -39,20 +38,24 @@ svg-sprites --mode <mode> <path>
|
||||
| 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` |
|
||||
| Classic `stack` and `symbol` sprites | `legacy` |
|
||||
|
||||
Modern React and Next.js modes use a local `svg-sprite.config.ts`. Legacy mode uses a separate `svg-sprites.config.ts` and is covered in [its own guide](legacy.md).
|
||||
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 guides use `svg-sprite.config.ts` as the recommended name.
|
||||
|
||||
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`.
|
||||
|
||||
Available options are `--mode`, `--name`, `--description`, `--input-folder`, repeatable `--input-file`, 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-file` replaces the complete config `inputFiles` array.
|
||||
|
||||
The mode must match the application's bundler. The generator creates different SVG asset integration code for Vite and for bundlers compatible with Webpack Asset Modules.
|
||||
|
||||
## React and Next.js configuration
|
||||
## Unified configuration
|
||||
|
||||
Each directory containing `svg-sprite.config.ts` defines one independent sprite.
|
||||
Each config file defines one independent sprite.
|
||||
|
||||
```ts
|
||||
import { defineNextSpriteConfig } from '@gromlab/svg-sprites'
|
||||
import { defineSpriteConfig } from '@gromlab/svg-sprites'
|
||||
|
||||
export default defineNextSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
name: 'app',
|
||||
description: 'Shared application icons',
|
||||
inputFolder: './local-icons',
|
||||
@@ -69,18 +72,13 @@ export default defineNextSpriteConfig({
|
||||
})
|
||||
```
|
||||
|
||||
For React, use `defineReactSpriteConfig`. The configuration contract is the same:
|
||||
|
||||
```ts
|
||||
import { defineReactSpriteConfig } from '@gromlab/svg-sprites'
|
||||
```
|
||||
|
||||
| Option | Type | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `mode` | `SpriteMode` | None | Generation mode; may be supplied by CLI/API |
|
||||
| `name` | `string` | Derived from the directory | Name of the sprite, component, and public types |
|
||||
| `description` | `string` | None | Description for types and the debug manifest |
|
||||
| `inputFolder` | `string` | `./icons` | SVG directory relative to the configuration file |
|
||||
| `inputFiles` | `string[]` | `[]` | Paths to individual SVG files relative to the configuration file |
|
||||
| `inputFolder` | `string` | `./icons` | SVG directory relative to the module root |
|
||||
| `inputFiles` | `string[]` | `[]` | Paths to individual SVG files relative to the module root |
|
||||
| `transform` | `TransformOptions` | All enabled | SVG preparation settings |
|
||||
| `generatedNotice` | `boolean` | `true` | Full or abbreviated warning in generated files |
|
||||
|
||||
@@ -112,28 +110,41 @@ After generation, the sprite directory looks like this:
|
||||
```text
|
||||
app-icons/
|
||||
├── .gitignore
|
||||
├── index.ts
|
||||
├── manifest.ts
|
||||
├── svg-sprite.config.ts
|
||||
└── generated/
|
||||
├── .svg-sprites.manifest.json
|
||||
├── react-component.tsx
|
||||
├── index.ts # optional user-owned barrel
|
||||
└── .svg-sprite/
|
||||
├── state.json
|
||||
├── index.js
|
||||
├── index.d.ts
|
||||
├── icon-data.js
|
||||
├── icon-data.d.ts
|
||||
├── sprite.svg
|
||||
├── styles.module.css
|
||||
└── types.ts
|
||||
├── svg-sprite.manifest.js
|
||||
├── svg-sprite.manifest.d.ts
|
||||
└── react/
|
||||
├── react-component.js
|
||||
├── react-component.d.ts
|
||||
└── react-component.module.css
|
||||
```
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `index.ts` | Production exports for the component, props, styles, and icon names |
|
||||
| `manifest.ts` | Debug metadata and the asset URL for `SpriteViewer` |
|
||||
| `generated/sprite.svg` | Compiled SVG sprite |
|
||||
| `generated/react-component.tsx` | Typed React component |
|
||||
| `generated/styles.module.css` | Base styles and transitions |
|
||||
| `generated/types.ts` | Runtime list and union type of icon names |
|
||||
| `generated/.svg-sprites.manifest.json` | List of files managed by the generator |
|
||||
| `.svg-sprite/index.js` | Production exports for the component and runtime icon-name list |
|
||||
| `.svg-sprite/index.d.ts` | Public declarations for the component, props, styles, 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 |
|
||||
| `.svg-sprite/state.json` | Mode, contract version, and managed file list |
|
||||
|
||||
The generator overwrites and deletes only files that contain its marker. If a user file occupies a managed path, generation fails.
|
||||
The generator overwrites and deletes only files that contain its marker. If a user file occupies a managed path, generation fails. The root `index.ts` is user-owned; create a barrel when needed:
|
||||
|
||||
```ts
|
||||
export * from './.svg-sprite'
|
||||
```
|
||||
|
||||
## React component and TypeScript
|
||||
|
||||
@@ -224,12 +235,11 @@ For multiple sprites, add a separate CLI command for each directory or combine t
|
||||
|
||||
## Formats and rendering methods
|
||||
|
||||
Modern React and Next.js modes generate the `stack` format. Legacy mode supports both `stack` and `symbol`.
|
||||
React and Next.js modes generate the `stack` format.
|
||||
|
||||
| Format | `<svg><use>` | `<img>` | CSS background |
|
||||
|---|---:|---:|---:|
|
||||
| `stack` | Yes | Yes | Yes |
|
||||
| `symbol` | Yes | No | No |
|
||||
|
||||
### Generated component
|
||||
|
||||
@@ -246,13 +256,13 @@ How you obtain `spriteUrl` depends on the bundler.
|
||||
Vite:
|
||||
|
||||
```ts
|
||||
import spriteUrl from './generated/sprite.svg?no-inline'
|
||||
import spriteUrl from './.svg-sprite/sprite.svg?no-inline'
|
||||
```
|
||||
|
||||
Webpack 5, Turbopack, and Next.js:
|
||||
|
||||
```ts
|
||||
const spriteUrl = new URL('./generated/sprite.svg', import.meta.url).href
|
||||
const spriteUrl = new URL('./.svg-sprite/sprite.svg', import.meta.url).href
|
||||
```
|
||||
|
||||
After obtaining the URL, use it in JSX:
|
||||
@@ -277,7 +287,7 @@ An SVG inside `<img>` is isolated from the page's CSS. Setting `color` or `--ico
|
||||
|
||||
```css
|
||||
.icon {
|
||||
background: url('./generated/sprite.svg#search') center / contain no-repeat;
|
||||
background: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -286,7 +296,7 @@ For a single-color silhouette, you can use a mask:
|
||||
```css
|
||||
.icon {
|
||||
background-color: currentColor;
|
||||
mask: url('./generated/sprite.svg#search') center / contain no-repeat;
|
||||
mask: url('./.svg-sprite/sprite.svg#search') center / contain no-repeat;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -300,7 +310,7 @@ The generated component 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 the generated TSX.
|
||||
- SVG path data is not serialized into generated JavaScript.
|
||||
|
||||
With standard asset naming, the bundler adds a content hash:
|
||||
|
||||
@@ -325,7 +335,8 @@ All transformations are enabled by default and can be configured independently:
|
||||
To disable an individual operation:
|
||||
|
||||
```ts
|
||||
export default defineNextSpriteConfig({
|
||||
export default defineSpriteConfig({
|
||||
mode: 'next@app/turbopack',
|
||||
transform: {
|
||||
removeSize: false,
|
||||
replaceColors: false,
|
||||
@@ -399,7 +410,7 @@ import { SpriteViewer } from '@gromlab/svg-sprites/react'
|
||||
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'
|
||||
|
||||
const sources = import.meta.glob<SpriteManifestModule>(
|
||||
'/src/**/svg-sprite/manifest.ts',
|
||||
'/src/**/svg-sprite/.svg-sprite/svg-sprite.manifest.js',
|
||||
)
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
@@ -411,8 +422,8 @@ Webpack and Next.js:
|
||||
|
||||
```tsx
|
||||
const sources = [
|
||||
() => import('@/ui/app-icons/manifest'),
|
||||
() => import('@/features/analytics/icons/manifest'),
|
||||
() => import('@/ui/app-icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
() => import('@/features/analytics/icons/.svg-sprite/svg-sprite.manifest.js'),
|
||||
]
|
||||
|
||||
export const IconsDebugPage = () => (
|
||||
@@ -447,9 +458,7 @@ To synchronize it with the application theme:
|
||||
A modern sprite module creates a local `.gitignore` for:
|
||||
|
||||
```text
|
||||
/generated/
|
||||
/index.ts
|
||||
/manifest.ts
|
||||
/.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:
|
||||
@@ -457,7 +466,7 @@ Commit the local `.gitignore` to the repository once. It excludes the other gene
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"sprites": "svg-sprites --mode next@app/turbopack src/ui/app-icons",
|
||||
"sprites": "svg-sprites src/ui/app-icons/svg-sprite.config.ts",
|
||||
"predev": "npm run sprites",
|
||||
"prebuild": "npm run sprites",
|
||||
"pretypecheck": "npm run sprites"
|
||||
@@ -467,18 +476,19 @@ Commit the local `.gitignore` to the repository once. It excludes the other gene
|
||||
|
||||
CI must install development dependencies and run the generation script before building or type-checking.
|
||||
|
||||
If the sprite directory already contains a user-created `.gitignore`, `index.ts`, or `manifest.ts`, the generator will not overwrite it. Move the user file or choose a separate sprite directory.
|
||||
If the sprite directory already contains a user-created `.gitignore` or a user-owned file inside `.svg-sprite`, the generator will not overwrite it. The root `index.ts` remains user-owned and may re-export the generated API.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Missing `index.ts`: run the generation script before importing the module.
|
||||
- Configuration not found: check the CLI path and the `svg-sprite.config.ts` file name.
|
||||
- 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 `inputFiles`, the `.svg` extension, and the nesting level under `inputFolder`.
|
||||
- Name conflict: two different SVG files have the same basename; rename one of them.
|
||||
- `Refusing to overwrite a user file`: a file without the generated marker occupies a managed path.
|
||||
- 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.
|
||||
- The Viewer cannot find the sprite: check the path to `manifest.ts` and run generation before starting the application.
|
||||
- The Viewer cannot find the sprite: check the path to `.svg-sprite/svg-sprite.manifest.js` and 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).
|
||||
|
||||
Reference in New Issue
Block a user