feat: добавить серверную генерацию спрайтов

This commit is contained in:
2026-07-16 09:14:11 +03:00
parent e9ae91815a
commit 57342fae4e
379 changed files with 3108 additions and 655 deletions

View File

@@ -15,3 +15,5 @@ apps/*/public/sprites/
apps/*/static/sprites/
apps/*/*.tsbuildinfo
apps/*/src/sprite/.svg-sprite/
apps/*/src/*-icons/.svg-sprite/
apps/standalone-server/cases/*/.svg-sprite/

View File

@@ -39,6 +39,11 @@ production build и отображения внешнего SVG-спрайта
В verify-матрицу входят все exact modes из корневого `MODES_CHECKLIST.md`.
Отдельный fixture `standalone-server` проверяет mixed local/HTTP inputs, HTTP-only
input, отключённые transforms, два sprite profiles и server manifest. Затем каждое
из 29 consumer-приложений генерирует локальный `app-icons` и удалённо собранный
`remote-app-icons` с `source: "remote"`.
## Первый запуск
Из корня репозитория:
@@ -76,6 +81,8 @@ npm run dev --workspace @svg-sprites-fixtures/react-vite --prefix integration
наличие symbol ID, отсутствие browser errors и зелёные пиксели отрисованной иконки.
Для каждого active mode тест также открывает единый Viewer, проверяет его Shadow DOM,
совпадение sprite URL, карточку `check`, dialog и mode-specific вкладки кода.
В каждом consumer-приложении проверяются два разных SVG assets, две rendered-иконки
и группы `app`/`remote-app` в одном Viewer.
Static fixture копирует managed SVG и JSON manifest в `dist/app-icons/` и использует
literal `<use href="/app-icons/sprite.svg#check">`.

View File

@@ -4,7 +4,9 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.json",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.json",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && npm run typecheck && vite build",
"dev": "npm run sprites && vite"

View File

@@ -1,6 +1,6 @@
{
"mode": "alpine@vite",
"name": "icons",
"name": "app",
"input": "../../../../fixtures/icons/check.svg",
"generatedNotice": false
}

View File

@@ -1,22 +1,41 @@
import {
iconsAlpinePlugin,
iconsIconDirective,
iconsIconMagic,
iconsIconNames,
type IconsIconName,
} from './sprite/index.js'
appAlpinePlugin,
appIconDirective,
appIconMagic,
appIconNames,
type AppIconName,
} from './app-icons/index.js'
import {
remoteAppAlpinePlugin,
remoteAppIconDirective,
remoteAppIconMagic,
remoteAppIconNames,
type RemoteAppIconName,
} from './remote-app-icons/index.js'
declare const Alpine: { plugin(plugin: typeof iconsAlpinePlugin): void }
declare const Alpine: {
plugin(plugin: typeof appAlpinePlugin | typeof remoteAppAlpinePlugin): void
}
const iconName: IconsIconName = iconsIconNames[0]
const directive: 'icons-icon' = iconsIconDirective
const magic: 'iconsIconHref' = iconsIconMagic
const appIconName: AppIconName = appIconNames[0]
const appDirective: 'app-icon' = appIconDirective
const appMagic: 'appIconHref' = appIconMagic
const remoteAppIconName: RemoteAppIconName = remoteAppIconNames[0]
const remoteAppDirective: 'remote-app-icon' = remoteAppIconDirective
const remoteAppMagic: 'remoteAppIconHref' = remoteAppIconMagic
Alpine.plugin(iconsAlpinePlugin)
void iconName
void directive
void magic
Alpine.plugin(appAlpinePlugin)
Alpine.plugin(remoteAppAlpinePlugin)
void appIconName
void appDirective
void appMagic
void remoteAppIconName
void remoteAppDirective
void remoteAppMagic
// @ts-expect-error Generated icon names form a literal union.
const missingIcon: IconsIconName = 'missing'
const missingIcon: AppIconName = 'missing'
void missingIcon
// @ts-expect-error Generated remote icon names form a literal union.
const missingRemoteIcon: RemoteAppIconName = 'missing'
void missingRemoteIcon

View File

@@ -1,9 +1,12 @@
import '@gromlab/svg-sprites/viewer/element'
import Alpine from 'alpinejs'
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
import { iconsAlpinePlugin } from './sprite/index.js'
import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import { appAlpinePlugin } from './app-icons/index.js'
import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
import { remoteAppAlpinePlugin } from './remote-app-icons/index.js'
Alpine.plugin(iconsAlpinePlugin)
Alpine.plugin(appAlpinePlugin)
Alpine.plugin(remoteAppAlpinePlugin)
window.Alpine = Alpine
document.querySelector('#app').innerHTML = `
@@ -12,14 +15,22 @@ document.querySelector('#app').innerHTML = `
<svg
data-testid="icon"
data-app="alpine-vite"
x-icons-icon="'check'"
x-app-icon="'check'"
role="img"
aria-label="Check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></svg>
<svg
data-testid="remote-icon"
data-app="alpine-vite-remote"
x-remote-app-icon="'check'"
role="img"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></svg>
<gromlab-sprite-viewer viewer-title="Alpine Vite Viewer"></gromlab-sprite-viewer>
</main>
`
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest]
Alpine.start()

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'alpine@vite',
source: 'remote',
input: manifestUrl,
}

View File

@@ -4,7 +4,9 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.json",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.json",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && npm run typecheck && webpack --mode production",
"dev": "npm run sprites && webpack serve --mode development"

View File

@@ -1,6 +1,6 @@
{
"mode": "alpine@webpack",
"name": "icons",
"name": "app",
"input": "../../../../fixtures/icons/check.svg",
"generatedNotice": false
}

View File

@@ -1,22 +1,41 @@
import {
iconsAlpinePlugin,
iconsIconDirective,
iconsIconMagic,
iconsIconNames,
type IconsIconName,
} from './sprite/index.js'
appAlpinePlugin,
appIconDirective,
appIconMagic,
appIconNames,
type AppIconName,
} from './app-icons/index.js'
import {
remoteAppAlpinePlugin,
remoteAppIconDirective,
remoteAppIconMagic,
remoteAppIconNames,
type RemoteAppIconName,
} from './remote-app-icons/index.js'
declare const Alpine: { plugin(plugin: typeof iconsAlpinePlugin): void }
declare const Alpine: {
plugin(plugin: typeof appAlpinePlugin | typeof remoteAppAlpinePlugin): void
}
const iconName: IconsIconName = iconsIconNames[0]
const directive: 'icons-icon' = iconsIconDirective
const magic: 'iconsIconHref' = iconsIconMagic
const appIconName: AppIconName = appIconNames[0]
const appDirective: 'app-icon' = appIconDirective
const appMagic: 'appIconHref' = appIconMagic
const remoteAppIconName: RemoteAppIconName = remoteAppIconNames[0]
const remoteAppDirective: 'remote-app-icon' = remoteAppIconDirective
const remoteAppMagic: 'remoteAppIconHref' = remoteAppIconMagic
Alpine.plugin(iconsAlpinePlugin)
void iconName
void directive
void magic
Alpine.plugin(appAlpinePlugin)
Alpine.plugin(remoteAppAlpinePlugin)
void appIconName
void appDirective
void appMagic
void remoteAppIconName
void remoteAppDirective
void remoteAppMagic
// @ts-expect-error Generated icon names form a literal union.
const missingIcon: IconsIconName = 'missing'
const missingIcon: AppIconName = 'missing'
void missingIcon
// @ts-expect-error Generated remote icon names form a literal union.
const missingRemoteIcon: RemoteAppIconName = 'missing'
void missingRemoteIcon

View File

@@ -1,9 +1,12 @@
import '@gromlab/svg-sprites/viewer/element'
import Alpine from 'alpinejs'
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
import { iconsAlpinePlugin } from './sprite/index.js'
import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import { appAlpinePlugin } from './app-icons/index.js'
import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
import { remoteAppAlpinePlugin } from './remote-app-icons/index.js'
Alpine.plugin(iconsAlpinePlugin)
Alpine.plugin(appAlpinePlugin)
Alpine.plugin(remoteAppAlpinePlugin)
window.Alpine = Alpine
document.querySelector('#app').innerHTML = `
@@ -12,14 +15,22 @@ document.querySelector('#app').innerHTML = `
<svg
data-testid="icon"
data-app="alpine-webpack"
x-icons-icon="'check'"
x-app-icon="'check'"
role="img"
aria-label="Check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></svg>
<svg
data-testid="remote-icon"
data-app="alpine-webpack-remote"
x-remote-app-icon="'check'"
role="img"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></svg>
<gromlab-sprite-viewer viewer-title="Alpine Webpack Viewer"></gromlab-sprite-viewer>
</main>
`
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest]
Alpine.start()

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'alpine@webpack',
source: 'remote',
input: manifestUrl,
}

View File

@@ -3,7 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "ngc -p tsconfig.json --noEmit",
"build": "npm run sprites && webpack --mode production",
"dev": "npm run sprites && webpack serve --mode development"

View File

@@ -1,6 +1,6 @@
export default {
mode: 'angular@webpack',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
}

View File

@@ -3,24 +3,32 @@ import '@gromlab/svg-sprites/viewer/element'
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'
import { bootstrapApplication } from '@angular/platform-browser'
import { IconsIcon } from './sprite'
import { AppIcon } from './app-icons'
import { RemoteAppIcon } from './remote-app-icons'
import './type-probe'
@Component({
selector: 'app-root',
standalone: true,
imports: [IconsIcon],
imports: [AppIcon, RemoteAppIcon],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<main>
<h1>Angular + Webpack</h1>
<icons-icon
<app-icon
data-testid="icon"
data-app="angular-webpack"
icon="check"
aria-label="Check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
/>
<remote-app-icon
data-testid="remote-icon"
data-app="angular-webpack-remote"
icon="check"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
/>
<gromlab-sprite-viewer
[sources]="viewerSources"
viewer-title="Angular Webpack Viewer"
@@ -30,7 +38,8 @@ import './type-probe'
})
class AppComponent {
readonly viewerSources = [
() => import('./sprite/.svg-sprite/svg-sprite.manifest.js'),
() => import('./app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('./remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
]
}

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'angular@webpack',
source: 'remote',
input: manifestUrl,
}

View File

@@ -1,8 +1,11 @@
import type { IconsIconName } from './sprite'
import type { AppIconName } from './app-icons'
import type { RemoteAppIconName } from './remote-app-icons'
const validIcon: IconsIconName = 'check'
const validIcon: AppIconName = 'check'
const validRemoteIcon: RemoteAppIconName = 'check'
void validIcon
void validRemoteIcon
// @ts-expect-error generated icon names are a closed union
const invalidIcon: IconsIconName = 'missing'
const invalidIcon: AppIconName = 'missing'
void invalidIcon

View File

@@ -3,7 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "ngc -p tsconfig.app.json --noEmit",
"build": "npm run sprites && ng build --configuration production",
"dev": "npm run sprites && ng serve"

View File

@@ -0,0 +1 @@
export * from './.svg-sprite/index'

View File

@@ -1,6 +1,6 @@
export default {
mode: 'angular@application',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
}

View File

@@ -2,22 +2,30 @@ import '@gromlab/svg-sprites/viewer/element'
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'
import { IconsIcon } from './sprite'
import { AppIcon } from './app-icons'
import { RemoteAppIcon } from './remote-app-icons'
@Component({
selector: 'app-root',
standalone: true,
imports: [IconsIcon],
imports: [AppIcon, RemoteAppIcon],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<main>
<h1>Angular application builder</h1>
<icons-icon
<app-icon
data-testid="icon"
data-app="angular"
icon="check"
aria-label="Check icon"
style="color: #16a34a; --icon-color-1: #16a34a"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
/>
<remote-app-icon
data-testid="remote-icon"
data-app="angular-remote"
icon="check"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
/>
<gromlab-sprite-viewer
[sources]="viewerSources"
@@ -28,6 +36,7 @@ import { IconsIcon } from './sprite'
})
export class AppComponent {
readonly viewerSources = [
() => import('./sprite/.svg-sprite/svg-sprite.manifest.js'),
() => import('./app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('./remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
]
}

View File

@@ -0,0 +1 @@
export * from './.svg-sprite/index'

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'angular@application',
source: 'remote',
input: manifestUrl,
}

View File

@@ -9,7 +9,8 @@ body {
padding: 40px;
}
icons-icon[data-testid='icon'] {
app-icon[data-testid='icon'],
remote-app-icon[data-testid='remote-icon'] {
width: 64px;
height: 64px;
color: #16a34a;

View File

@@ -1,10 +1,14 @@
import type { IconsIconName } from './sprite'
import type { SpriteManifest } from './sprite/.svg-sprite/svg-sprite.manifest.js'
import type { AppIconName } from './app-icons'
import type { SpriteManifest as AppSpriteManifest } from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import type { RemoteAppIconName } from './remote-app-icons'
import type { SpriteManifest as RemoteAppSpriteManifest } from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
const icon: IconsIconName = 'check'
const mode: SpriteManifest['mode'] = 'angular@application'
const icon: AppIconName = 'check'
const remoteIcon: RemoteAppIconName = 'check'
const mode: AppSpriteManifest['mode'] = 'angular@application'
const remoteMode: RemoteAppSpriteManifest['mode'] = 'angular@application'
// @ts-expect-error Unknown source file names are rejected by the generated union.
const unknownIcon: IconsIconName = 'missing'
const unknownIcon: AppIconName = 'missing'
export { icon, mode, unknownIcon }
export { icon, mode, remoteIcon, remoteMode, unknownIcon }

View File

@@ -4,7 +4,9 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "astro check",
"build": "npm run sprites && astro check && astro build",
"dev": "npm run sprites && astro dev"

View File

@@ -1,6 +1,6 @@
export default {
mode: 'astro@vite',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
}

View File

@@ -1,5 +1,6 @@
---
import { IconsIcon } from '../sprite/index.js'
import { AppIcon } from '../app-icons/index.js'
import { RemoteAppIcon } from '../remote-app-icons/index.js'
const title = 'Astro sprite fixture'
---
@@ -14,14 +15,23 @@ const title = 'Astro sprite fixture'
<body>
<main>
<h1>Astro</h1>
<IconsIcon
<AppIcon
data-testid="icon"
data-app="astro"
icon="check"
aria-label="Check icon"
width="64"
height="64"
style="--icon-color-1: #16a34a"
style="color: #16a34a; --icon-color-1: #16a34a"
/>
<RemoteAppIcon
data-testid="remote-icon"
data-app="astro-remote"
icon="check"
aria-label="Remote check icon"
width="64"
height="64"
style="color: #16a34a; --icon-color-1: #16a34a"
/>
<gromlab-sprite-viewer id="sprite-viewer"></gromlab-sprite-viewer>
</main>
@@ -34,7 +44,10 @@ const title = 'Astro sprite fixture'
if (!viewer) throw new Error('Sprite Viewer element is missing.')
Object.assign(viewer, {
viewerTitle: 'Astro Vite Viewer',
sources: [() => import('../sprite/.svg-sprite/svg-sprite.manifest.js')],
sources: [
() => import('../app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('../remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
],
})
</script>
</body>
@@ -52,7 +65,8 @@ const title = 'Astro sprite fixture'
padding: 40px;
}
[data-testid='icon'] {
[data-testid='icon'],
[data-testid='remote-icon'] {
width: 64px;
height: 64px;
color: #16a34a;

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'astro@vite',
source: 'remote',
input: manifestUrl,
}

View File

@@ -1,11 +1,16 @@
import type { IconsIconName, IconsIconProps } from './sprite/index.js'
import type { SpriteManifest } from './sprite/.svg-sprite/svg-sprite.manifest.js'
import type { AppIconName, AppIconProps } from './app-icons/index.js'
import type { SpriteManifest } from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons/index.js'
import type { SpriteManifest as RemoteSpriteManifest } from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
const icon: IconsIconName = 'check'
const props: IconsIconProps = { icon, width: 24, 'aria-label': 'Check icon' }
const icon: AppIconName = 'check'
const remoteIcon: RemoteAppIconName = 'check'
const props: AppIconProps = { icon, width: 24, 'aria-label': 'Check icon' }
const remoteProps: RemoteAppIconProps = { icon: remoteIcon, width: 24, 'aria-label': 'Remote check icon' }
const framework: SpriteManifest['usage']['framework'] = 'astro'
const remoteFramework: RemoteSpriteManifest['usage']['framework'] = 'astro'
// @ts-expect-error Unknown source file names are rejected by the generated union.
const unknownIcon: IconsIconName = 'missing'
const unknownIcon: AppIconName = 'missing'
export { framework, icon, props, unknownIcon }
export { framework, icon, props, remoteFramework, remoteIcon, remoteProps, unknownIcon }

View File

@@ -4,7 +4,9 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.json",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.json",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && npm run typecheck && vite build",
"dev": "npm run sprites && vite"

View File

@@ -1,6 +1,6 @@
{
"mode": "lit@vite",
"name": "icons",
"name": "app",
"input": "../../../../fixtures/icons/check.svg",
"generatedNotice": false
}

View File

@@ -1,18 +1,33 @@
import {
defineIconsIcon,
IconsIcon,
iconsIconNames,
iconsIconTagName,
type IconsIconName,
} from './sprite/index.js'
AppIcon,
appIconNames,
appIconTagName,
defineAppIcon,
type AppIconName,
} from './app-icons/index.js'
import {
defineRemoteAppIcon,
RemoteAppIcon,
remoteAppIconNames,
remoteAppIconTagName,
type RemoteAppIconName,
} from './remote-app-icons/index.js'
const iconName: IconsIconName = iconsIconNames[0]
const icon = new IconsIcon()
icon.icon = iconName
const appIconName: AppIconName = appIconNames[0]
const appIcon = new AppIcon()
appIcon.icon = appIconName
const remoteAppIconName: RemoteAppIconName = remoteAppIconNames[0]
const remoteAppIcon = new RemoteAppIcon()
remoteAppIcon.icon = remoteAppIconName
const registeredIcon = document.createElement(iconsIconTagName)
registeredIcon.icon = 'check'
defineIconsIcon()
const registeredAppIcon = document.createElement(appIconTagName)
registeredAppIcon.icon = 'check'
const registeredRemoteAppIcon = document.createElement(remoteAppIconTagName)
registeredRemoteAppIcon.icon = 'check'
defineAppIcon()
defineRemoteAppIcon()
// @ts-expect-error Generated icon names form a literal union.
registeredIcon.icon = 'missing'
registeredAppIcon.icon = 'missing'
// @ts-expect-error Generated remote icon names form a literal union.
registeredRemoteAppIcon.icon = 'missing'

View File

@@ -1,20 +1,31 @@
import '@gromlab/svg-sprites/viewer/element'
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
import { defineIconsIcon } from './sprite/index.js'
import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import { defineAppIcon } from './app-icons/index.js'
import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
import { defineRemoteAppIcon } from './remote-app-icons/index.js'
defineIconsIcon()
defineAppIcon()
defineRemoteAppIcon()
document.querySelector('#app').innerHTML = `
<h1>Lit + Vite</h1>
<icons-icon
<app-icon
data-testid="icon"
data-app="lit-vite"
icon="check"
role="img"
aria-label="Check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></icons-icon>
></app-icon>
<remote-app-icon
data-testid="remote-icon"
data-app="lit-vite-remote"
icon="check"
role="img"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></remote-app-icon>
<gromlab-sprite-viewer viewer-title="Lit Vite Viewer"></gromlab-sprite-viewer>
`
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest]

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'lit@vite',
source: 'remote',
input: manifestUrl,
}

View File

@@ -4,7 +4,9 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.json",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.json",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && npm run typecheck && webpack --mode production",
"dev": "npm run sprites && webpack serve --mode development"

View File

@@ -1,6 +1,6 @@
{
"mode": "lit@webpack",
"name": "icons",
"name": "app",
"input": "../../../../fixtures/icons/check.svg",
"generatedNotice": false
}

View File

@@ -1,18 +1,33 @@
import {
defineIconsIcon,
IconsIcon,
iconsIconNames,
iconsIconTagName,
type IconsIconName,
} from './sprite/index.js'
AppIcon,
appIconNames,
appIconTagName,
defineAppIcon,
type AppIconName,
} from './app-icons/index.js'
import {
defineRemoteAppIcon,
RemoteAppIcon,
remoteAppIconNames,
remoteAppIconTagName,
type RemoteAppIconName,
} from './remote-app-icons/index.js'
const iconName: IconsIconName = iconsIconNames[0]
const icon = new IconsIcon()
icon.icon = iconName
const appIconName: AppIconName = appIconNames[0]
const appIcon = new AppIcon()
appIcon.icon = appIconName
const remoteAppIconName: RemoteAppIconName = remoteAppIconNames[0]
const remoteAppIcon = new RemoteAppIcon()
remoteAppIcon.icon = remoteAppIconName
const registeredIcon = document.createElement(iconsIconTagName)
registeredIcon.icon = 'check'
defineIconsIcon()
const registeredAppIcon = document.createElement(appIconTagName)
registeredAppIcon.icon = 'check'
const registeredRemoteAppIcon = document.createElement(remoteAppIconTagName)
registeredRemoteAppIcon.icon = 'check'
defineAppIcon()
defineRemoteAppIcon()
// @ts-expect-error Generated icon names form a literal union.
registeredIcon.icon = 'missing'
registeredAppIcon.icon = 'missing'
// @ts-expect-error Generated remote icon names form a literal union.
registeredRemoteAppIcon.icon = 'missing'

View File

@@ -1,20 +1,31 @@
import '@gromlab/svg-sprites/viewer/element'
import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js'
import { defineIconsIcon } from './sprite/index.js'
import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js'
import { defineAppIcon } from './app-icons/index.js'
import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js'
import { defineRemoteAppIcon } from './remote-app-icons/index.js'
defineIconsIcon()
defineAppIcon()
defineRemoteAppIcon()
document.querySelector('#app').innerHTML = `
<h1>Lit + Webpack</h1>
<icons-icon
<app-icon
data-testid="icon"
data-app="lit-webpack"
icon="check"
role="img"
aria-label="Check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></icons-icon>
></app-icon>
<remote-app-icon
data-testid="remote-icon"
data-app="lit-webpack-remote"
icon="check"
role="img"
aria-label="Remote check icon"
style="width:64px;height:64px;color:#16a34a;--icon-color-1:#16a34a"
></remote-app-icon>
<gromlab-sprite-viewer viewer-title="Lit Webpack Viewer"></gromlab-sprite-viewer>
`
document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest]
document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest]

View File

@@ -0,0 +1,8 @@
const manifestUrl = process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json'
export default {
mode: 'lit@webpack',
source: 'remote',
input: manifestUrl,
}

View File

@@ -1,11 +1,12 @@
import { IconsIcon } from '../src/sprite'
import { AppIcon } from '../src/app-icons'
import { RemoteAppIcon } from '../src/remote-app-icons'
import { AppSpriteViewer } from './sprite-viewer'
export default function Page() {
return (
<main>
<h1>Next.js App Router + Turbopack</h1>
<IconsIcon
<AppIcon
data-testid="icon"
data-app="next-app-turbopack"
icon="check"
@@ -14,6 +15,15 @@ export default function Page() {
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<RemoteAppIcon
data-testid="remote-icon"
data-app="next-app-turbopack-remote"
icon="check"
aria-label="Remote check icon"
width={64}
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<AppSpriteViewer />
</main>
)

View File

@@ -3,7 +3,8 @@
import { SpriteViewer } from '@gromlab/svg-sprites/react'
const viewerSources = [
() => import('../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
] as const
export function AppSpriteViewer() {

View File

@@ -1,18 +1,28 @@
import { IconsIcon, iconsIconNames } from './src/sprite'
import type { IconsIconName, IconsIconProps, IconsIconStyle } from './src/sprite'
import { IconsIcon as GeneratedIconsIcon } from './src/sprite/.svg-sprite/react/react-component.js'
import type { IconsIconName as GeneratedIconName } from './src/sprite/.svg-sprite/icon-data.js'
import { iconsIconNames as generatedIconNames } from './src/sprite/.svg-sprite/icon-data.js'
import { AppIcon, appIconNames } from './src/app-icons'
import type { AppIconName, AppIconProps, AppIconStyle } from './src/app-icons'
import { AppIcon as GeneratedAppIcon } from './src/app-icons/.svg-sprite/react/react-component.js'
import type { AppIconName as GeneratedAppIconName } from './src/app-icons/.svg-sprite/icon-data.js'
import { appIconNames as generatedAppIconNames } from './src/app-icons/.svg-sprite/icon-data.js'
import { RemoteAppIcon, remoteAppIconNames } from './src/remote-app-icons'
import type { RemoteAppIconName, RemoteAppIconProps } from './src/remote-app-icons'
import { RemoteAppIcon as GeneratedRemoteAppIcon } from './src/remote-app-icons/.svg-sprite/react/react-component.js'
import type { RemoteAppIconName as GeneratedRemoteAppIconName } from './src/remote-app-icons/.svg-sprite/icon-data.js'
import { remoteAppIconNames as generatedRemoteAppIconNames } from './src/remote-app-icons/.svg-sprite/icon-data.js'
const iconName: IconsIconName = iconsIconNames[0]
const generatedIconName: GeneratedIconName = generatedIconNames[0]
const allIconNames: readonly IconsIconName[] = iconsIconNames
const style: IconsIconStyle = { '--icon-color-1': '#16a34a' }
const props: IconsIconProps = { icon: iconName, style }
const appIconName: AppIconName = appIconNames[0]
const generatedAppIconName: GeneratedAppIconName = generatedAppIconNames[0]
const allAppIconNames: readonly AppIconName[] = appIconNames
const style: AppIconStyle = { '--icon-color-1': '#16a34a' }
const appProps: AppIconProps = { icon: appIconName, style }
const remoteAppIconName: RemoteAppIconName = remoteAppIconNames[0]
const generatedRemoteAppIconName: GeneratedRemoteAppIconName = generatedRemoteAppIconNames[0]
const remoteAppProps: RemoteAppIconProps = { icon: remoteAppIconName, style }
void allIconNames
void <IconsIcon {...props} />
void <GeneratedIconsIcon icon={generatedIconName} />
void allAppIconNames
void <AppIcon {...appProps} />
void <GeneratedAppIcon icon={generatedAppIconName} />
void <RemoteAppIcon {...remoteAppProps} />
void <GeneratedRemoteAppIcon icon={generatedRemoteAppIconName} />
// @ts-expect-error Unknown icon names must be rejected by generated declarations.
void <IconsIcon icon="missing" />
void <AppIcon icon="missing" />

View File

@@ -3,7 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && next build --turbopack",
"dev": "npm run sprites && next dev --turbopack",

View File

@@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites'
export default defineSpriteConfig({
mode: 'next@app/turbopack',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
})

View File

@@ -0,0 +1,6 @@
export default {
mode: 'next@app/turbopack',
source: 'remote',
input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json',
}

View File

@@ -1,11 +1,12 @@
import { IconsIcon } from '../src/sprite'
import { AppIcon } from '../src/app-icons'
import { RemoteAppIcon } from '../src/remote-app-icons'
import { AppSpriteViewer } from './sprite-viewer'
export default function Page() {
return (
<main>
<h1>Next.js App Router + Webpack</h1>
<IconsIcon
<AppIcon
data-testid="icon"
data-app="next-app-webpack"
icon="check"
@@ -14,6 +15,15 @@ export default function Page() {
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<RemoteAppIcon
data-testid="remote-icon"
data-app="next-app-webpack-remote"
icon="check"
aria-label="Remote check icon"
width={64}
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<AppSpriteViewer />
</main>
)

View File

@@ -3,7 +3,8 @@
import { SpriteViewer } from '@gromlab/svg-sprites/react'
const viewerSources = [
() => import('../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
] as const
export function AppSpriteViewer() {

View File

@@ -3,7 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && next build --webpack",
"dev": "npm run sprites && next dev --webpack",

View File

@@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites'
export default defineSpriteConfig({
mode: 'next@app/webpack',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
})

View File

@@ -0,0 +1,6 @@
export default {
mode: 'next@app/webpack',
source: 'remote',
input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL
?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json',
}

View File

@@ -3,7 +3,9 @@
"private": true,
"version": "0.0.0",
"scripts": {
"sprites": "svg-sprites src/sprite/svg-sprite.config.ts",
"sprites": "npm run sprites:local && npm run sprites:remote",
"sprites:local": "svg-sprites src/app-icons/svg-sprite.config.ts",
"sprites:remote": "svg-sprites src/remote-app-icons/svg-sprite.config.js",
"typecheck": "tsc --noEmit",
"build": "npm run sprites && next build --turbopack",
"dev": "npm run sprites && next dev --turbopack",

View File

@@ -1,15 +1,17 @@
import { SpriteViewer } from '@gromlab/svg-sprites/react'
import { IconsIcon } from '../src/sprite'
import { AppIcon } from '../src/app-icons'
import { RemoteAppIcon } from '../src/remote-app-icons'
const viewerSources = [
() => import('../src/sprite/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/app-icons/.svg-sprite/svg-sprite.manifest.js'),
() => import('../src/remote-app-icons/.svg-sprite/svg-sprite.manifest.js'),
] as const
export default function Page() {
return (
<main>
<h1>Next.js Pages Router + Turbopack</h1>
<IconsIcon
<AppIcon
data-testid="icon"
data-app="next-pages-turbopack"
icon="check"
@@ -18,6 +20,15 @@ export default function Page() {
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<RemoteAppIcon
data-testid="remote-icon"
data-app="next-pages-turbopack-remote"
icon="check"
aria-label="Remote check icon"
width={64}
height={64}
style={{ '--icon-color-1': '#16a34a' }}
/>
<SpriteViewer sources={viewerSources} title="Next Pages Turbopack Viewer" style={{ marginTop: 32 }} />
</main>
)

View File

@@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites'
export default defineSpriteConfig({
mode: 'next@pages/turbopack',
name: 'icons',
name: 'app',
input: '../../../../fixtures/icons/check.svg',
generatedNotice: false,
})

Some files were not shown because too many files have changed in this diff Show More