feat: standalone mode

This commit is contained in:
2026-07-14 08:34:45 +03:00
parent 3dd385bfda
commit c596f9f1c3
64 changed files with 1341 additions and 2755 deletions

View File

@@ -35,7 +35,7 @@ const upstream = [
export default [
{
name: 'svg-sprites',
description: 'Use only when configuring, generating, or troubleshooting @gromlab/svg-sprites. Triggers: @gromlab/svg-sprites, svg-sprite.config.ts, defineSpriteConfig, generateSprite, react@vite, react@webpack, next@app, next@pages, inputFiles, 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.ts, defineSpriteConfig, generateSprite, standalone, standalone@vite, standalone@webpack, react@vite, react@webpack, next@app, next@pages, inputFiles, 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',
maxSkillBytes: 48_000,
documents: documents('en'),
@@ -43,7 +43,7 @@ export default [
},
{
name: 'svg-sprites-ru',
description: 'Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.ts, defineSpriteConfig, generateSprite, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок.',
description: 'Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.ts, defineSpriteConfig, generateSprite, standalone, standalone@vite, standalone@webpack, react@vite, react@webpack, next@app, next@pages, inputFiles, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок.',
output: '../artifacts/svg-sprites-ru',
maxSkillBytes: 48_000,
documents: documents('ru'),

View File

@@ -1,15 +1,15 @@
## 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 the project's SVGs into an external cacheable sprite asset and, for React/Next.js, creates a typed component, a list of valid names, and a debug manifest.
`@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 the project's SVGs into an external sprite asset, supports standalone projects, and creates typed components for React/Next.js.
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;
- icon name types;
- React component;
- production entry point `.svg-sprite/index.js` with `.d.ts`;
- debug entry point `.svg-sprite/svg-sprite.manifest.js` with `.d.ts`.
- mode-specific manifest data;
- icon name types and `.svg-sprite/index.js` for bundler modes;
- a React component only for React/Next.js;
- a deployment-neutral JSON manifest without a public URL for bare `standalone`.
The project determines how many sprite directories exist and where they live. For example, `name: 'file-manager'` produces `FileManagerIcon`, while another directory with `name: 'navigation'` produces a separate `NavigationIcon`. The names `FileManagerIcon` and `fileManagerIconNames` used below are examples of the API for one possible sprite, not fixed package exports.
Generated production components do not import `@gromlab/svg-sprites` at runtime. Install the package as a development dependency so configuration helpers and the local CLI use the version recorded in the project's lockfile.
Generated production runtime does not import `@gromlab/svg-sprites` at runtime. Install the package as a development dependency so configuration helpers and the local CLI use the version recorded in the project's lockfile.

View File

@@ -4,6 +4,9 @@ Select exactly one supported mode key:
| Project | Mode key |
|---|---|
| Static HTML / custom publishing | `standalone` |
| Standalone + Vite | `standalone@vite` |
| Standalone + Webpack 5 | `standalone@webpack` |
| React + Vite | `react@vite` |
| React + Webpack 5 | `react@webpack` |
| Next.js App Router + Turbopack | `next@app/turbopack` |
@@ -24,4 +27,4 @@ The CLI accepts exactly one path. A `.ts`, `.js`, or `.json` file loads that exa
}
```
Do not use incomplete `react`, `next@app`, or `next@pages` keys, the removed `legacy` mode, or the not-yet-implemented `standalone` mode. Create one command per config file or directory when the project has multiple sprites.
Do not use incomplete `react`, `next@app`, `next@pages`, or `standalone@` keys, or the removed `legacy` mode. Use bare `standalone` only when the application publishes the SVG itself; use the complete Vite/Webpack key otherwise. Create one command per config file or directory when the project has multiple sprites.

View File

@@ -1,6 +1,6 @@
## Generated directory contract
After generation, the selected directory has this structure:
After generation, a React/Next directory has this structure:
```text
svg-sprite/
@@ -23,6 +23,10 @@ svg-sprite/
└── react-component.module.css
```
Standalone does 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.
Edit the source SVGs, selected config, and user-owned `index.ts`. Do not manually change `.gitignore` or anything in `.svg-sprite`: the next generation will overwrite them. To import from the sprite-module root, create a barrel:
```ts
@@ -36,9 +40,11 @@ The internal `index.js` exports the component from `react/react-component.js` an
The sprite remains a separate content-hashed asset; SVG path data is not embedded in JavaScript:
- `react@vite` generates a static `sprite.svg?no-inline` import, preventing Vite from inlining it;
- `standalone@vite` uses the same Vite asset mechanism but exports an href helper without React;
- `standalone@webpack` uses Webpack Asset Modules without React;
- React Webpack 5 and all Next modes generate `new URL('./sprite.svg', import.meta.url).href`, which must be processed by the selected bundler's Asset Modules;
- 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`.
Do not move the generated sprite into `public` or rewrite its URL manually. When changing the router or bundler, regenerate the sprite with the new full mode key.
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.

View File

@@ -1,15 +1,15 @@
## Что делает пакет
`@gromlab/svg-sprites` — CLI-генератор SVG-спрайтов для пользовательских SVG-файлов. Пакет не содержит собственного набора иконок: он собирает SVG проекта во внешний кешируемый sprite asset и для React/Next.js создаёт типизированный компонент, список допустимых имён и debug manifest.
`@gromlab/svg-sprites` — CLI-генератор SVG-спрайтов для пользовательских SVG-файлов. Пакет не содержит собственного набора иконок: он собирает SVG проекта во внешний sprite asset, поддерживает standalone-проекты и для React/Next.js создаёт типизированный компонент.
Пакет рассчитан на несколько независимых спрайтов в одном проекте. Каждый явно выбранный config-файл или config-less каталог описывает один спрайт и получает собственные:
- SVG asset;
- типы имён иконок;
- React-компонент;
- production entry `.svg-sprite/index.js` с `.d.ts`;
- debug entry `.svg-sprite/svg-sprite.manifest.js` с `.d.ts`.
- mode-specific manifest data;
- для bundler modes — типы имён и production entry `.svg-sprite/index.js`;
- только для React/Next.js — React-компонент;
- для bare `standalone` — deployment-neutral JSON manifest без публичного URL.
Количество и расположение каталогов определяет проект. Например, `name: 'file-manager'` создаёт `FileManagerIcon`, а другой каталог с `name: 'navigation'` создаст отдельный `NavigationIcon`. Имена `FileManagerIcon` и `fileManagerIconNames` ниже являются примерами API одного из возможных спрайтов, а не фиксированными экспортами пакета.
Generated production-компоненты не импортируют `@gromlab/svg-sprites` во время выполнения. Устанавливай пакет как development dependency, чтобы config helpers и локальный CLI использовали версию из lockfile проекта.
Generated production runtime не импортирует `@gromlab/svg-sprites` во время выполнения. Устанавливай пакет как development dependency, чтобы config helpers и локальный CLI использовали версию из lockfile проекта.

View File

@@ -4,6 +4,9 @@
| Проект | Mode key |
|---|---|
| Static HTML / собственная публикация | `standalone` |
| Standalone + Vite | `standalone@vite` |
| Standalone + Webpack 5 | `standalone@webpack` |
| React + Vite | `react@vite` |
| React + Webpack 5 | `react@webpack` |
| Next.js App Router + Turbopack | `next@app/turbopack` |
@@ -24,4 +27,4 @@ CLI принимает ровно один путь. Путь к файлу `.ts
}
```
Не используй неполные `react`, `next@app`, `next@pages`, удалённый `legacy` или ещё не реализованный `standalone`. Для нескольких спрайтов создай отдельную команду для каждого config-файла или каталога.
Не используй неполные `react`, `next@app`, `next@pages`, `standalone@` или удалённый `legacy`. Bare `standalone` выбирай только когда приложение само публикует SVG; для Vite/Webpack используй соответствующий полный key. Для нескольких спрайтов создай отдельную команду для каждого config-файла или каталога.

View File

@@ -1,6 +1,6 @@
## Контракт generated-каталога
После генерации выбранный каталог имеет следующий вид:
После генерации React/Next-каталог имеет следующий вид:
```text
svg-sprite/
@@ -23,6 +23,10 @@ svg-sprite/
└── react-component.module.css
```
Standalone не создаёт `react/`. Bare `standalone` генерирует `sprite.svg` и
`svg-sprite.manifest.json`; `standalone@vite`/`standalone@webpack` дополнительно
генерируют `index.*`, `icon-data.*` и resolved manifest.
Редактируй исходные SVG, config-файл и пользовательский `index.ts`. Не изменяй вручную `.gitignore` и содержимое `.svg-sprite`: повторная генерация их перезапишет. Для импорта из корня sprite-модуля создай barrel:
```ts
@@ -36,9 +40,11 @@ export * from './.svg-sprite'
Спрайт остаётся отдельным asset с content hash; SVG path-данные не встраиваются в JavaScript:
- `react@vite` генерирует статический импорт `sprite.svg?no-inline`, запрещающий Vite inline;
- `standalone@vite` использует тот же Vite asset-механизм, но экспортирует href helper без React;
- `standalone@webpack` использует Webpack Asset Modules без React;
- React Webpack 5 и все Next modes генерируют `new URL('./sprite.svg', import.meta.url).href`, который должен обработать Asset Modules соответствующего сборщика;
- кастомный Webpack SVG loader не должен перехватывать generated `sprite.svg`;
- в Next mode generated-компонент не содержит `'use client'` и работает в Server Components, SSR и SSG; не добавляй клиентскую границу только ради иконки;
- команда сборки Next и mode key должны совпадать: Turbopack с `.../turbopack`, Webpack с `.../webpack`.
Не перемещай generated sprite в `public` и не переписывай URL вручную. При смене роутера или сборщика перегенерируй спрайт с новым полным mode key.
Для bundler modes не перемещай generated sprite в `public` и не переписывай URL вручную. Для bare `standalone` не перемещай managed original: приложение может явно копировать его в deploy output и само отвечает за публичный URL и очистку копии. При смене mode перегенерируй спрайт с новым полным key.