From 57342fae4ec8091353f212d341378fca34742520 Mon Sep 17 00:00:00 2001 From: "S.Gromov" Date: Thu, 16 Jul 2026 09:14:11 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20=D1=81=D0=BF=D1=80=D0=B0=D0=B9=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 5 + FEATURES.md | 2 +- MODES_CHECKLIST.md | 1 + README.md | 22 ++- README_RU.md | 22 ++- docs/en/README.md | 8 +- docs/en/configuration.md | 40 +++++ docs/en/guides/README.md | 6 + docs/en/guides/standalone-server.md | 113 ++++++++++++ docs/en/reference/programmatic-api.md | 8 +- docs/en/reference/technical.md | 47 ++++- docs/ru/README.md | 8 +- docs/ru/configuration.md | 40 +++++ docs/ru/guides/AGENTS.md | 10 +- docs/ru/guides/README.md | 6 + docs/ru/guides/standalone-server.md | 113 ++++++++++++ docs/ru/reference/programmatic-api.md | 9 +- docs/ru/reference/technical.md | 47 ++++- integration/.gitignore | 2 + integration/README.md | 7 + integration/apps/alpine-vite/package.json | 4 +- .../src/{sprite => app-icons}/.gitignore | 0 .../src/{sprite => app-icons}/index.d.ts | 0 .../src/{sprite => app-icons}/index.js | 0 .../svg-sprite.config.json | 2 +- .../src/generated-contract.typecheck.ts | 49 ++++-- integration/apps/alpine-vite/src/main.js | 21 ++- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/alpine-webpack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons}/index.js | 0 .../svg-sprite.config.json | 2 +- .../src/generated-contract.typecheck.ts | 49 ++++-- integration/apps/alpine-webpack/src/main.js | 21 ++- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/angular-webpack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/{sprite => app-icons}/index.ts | 0 .../svg-sprite.config.ts | 2 +- integration/apps/angular-webpack/src/main.ts | 17 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.ts | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + .../apps/angular-webpack/src/type-probe.ts | 9 +- integration/apps/angular/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../apps/angular/src/app-icons/index.ts | 1 + .../svg-sprite.config.ts | 2 +- integration/apps/angular/src/app.component.ts | 19 +- .../src/remote-app-icons}/.gitignore | 0 .../angular/src/remote-app-icons/index.ts | 1 + .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/angular/src/styles.css | 3 +- integration/apps/angular/src/type-probe.ts | 16 +- integration/apps/astro/package.json | 4 +- .../sprite => astro/src/app-icons}/.gitignore | 0 .../sprite => astro/src/app-icons}/index.d.ts | 0 .../sprite => astro/src/app-icons}/index.js | 0 .../svg-sprite.config.ts | 2 +- integration/apps/astro/src/pages/index.astro | 24 ++- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/astro/src/type-probe.ts | 17 +- integration/apps/lit-vite/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons}/index.js | 0 .../svg-sprite.config.json | 2 +- .../src/generated-contract.typecheck.ts | 41 +++-- integration/apps/lit-vite/src/main.js | 23 ++- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/lit-webpack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons}/index.js | 0 .../svg-sprite.config.json | 2 +- .../src/generated-contract.typecheck.ts | 41 +++-- integration/apps/lit-webpack/src/main.js | 23 ++- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 8 + .../apps/next-app-turbopack/app/page.tsx | 14 +- .../next-app-turbopack/app/sprite-viewer.tsx | 3 +- .../generated-contract.typecheck.tsx | 38 ++-- .../apps/next-app-turbopack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/{sprite => app-icons}/index.ts | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.ts | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + .../apps/next-app-webpack/app/page.tsx | 14 +- .../next-app-webpack/app/sprite-viewer.tsx | 3 +- .../apps/next-app-webpack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.ts | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.ts | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + .../apps/next-pages-turbopack/package.json | 4 +- .../apps/next-pages-turbopack/pages/index.tsx | 17 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.ts | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.ts | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + .../apps/next-pages-webpack/package.json | 4 +- .../apps/next-pages-webpack/pages/index.tsx | 17 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons/index.ts} | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons/index.ts} | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/nuxt-vite/app/app.vue | 14 +- .../app/components/SpriteViewer.client.vue | 3 +- .../app/generated-contract.typecheck.ts | 27 ++- integration/apps/nuxt-vite/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons}/index.js | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/nuxt-webpack/app/app.vue | 14 +- .../app/components/SpriteViewer.client.vue | 3 +- .../app/generated-contract.typecheck.ts | 27 ++- integration/apps/nuxt-webpack/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons}/index.js | 0 .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/preact-vite/package.json | 4 +- .../src/app-icons}/.gitignore | 0 .../src/app-icons}/index.d.ts | 0 .../src/app-icons/index.js} | 0 .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 23 ++- integration/apps/preact-vite/src/main.js | 17 +- .../src/remote-app-icons}/.gitignore | 0 .../src/remote-app-icons}/index.d.ts | 0 .../src/remote-app-icons/index.js} | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/preact-webpack/package.json | 4 +- .../preact-webpack/src/app-icons/.gitignore | 2 + .../preact-webpack/src/app-icons/index.d.ts | 1 + .../preact-webpack/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 23 ++- integration/apps/preact-webpack/src/main.js | 17 +- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/qwik-vite/package.json | 4 +- .../apps/qwik-vite/src/app-icons/.gitignore | 2 + .../apps/qwik-vite/src/app-icons/index.d.ts | 1 + .../src/app-icons}/index.js | 0 .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 23 ++- .../qwik-vite/src/remote-app-icons/.gitignore | 2 + .../qwik-vite/src/remote-app-icons/index.d.ts | 1 + .../src/remote-app-icons}/index.js | 0 .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/qwik-vite/src/root.jsx | 19 +- integration/apps/react-vite/package.json | 4 +- .../apps/react-vite/src/app-icons/.gitignore | 2 + .../apps/react-vite/src/app-icons/index.ts | 1 + .../svg-sprite.config.ts | 2 +- integration/apps/react-vite/src/main.tsx | 17 +- .../src/remote-app-icons/.gitignore | 2 + .../react-vite/src/remote-app-icons/index.ts | 1 + .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/react-webpack/package.json | 4 +- .../react-webpack/src/app-icons/.gitignore | 2 + .../apps/react-webpack/src/app-icons/index.ts | 1 + .../svg-sprite.config.ts | 2 +- integration/apps/react-webpack/src/main.tsx | 17 +- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.ts | 1 + .../src/remote-app-icons/svg-sprite.config.js | 6 + .../apps/solid-start-vite/package.json | 4 +- .../solid-start-vite/src/app-icons/.gitignore | 2 + .../solid-start-vite/src/app-icons/index.d.ts | 1 + .../solid-start-vite/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 21 ++- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 8 + .../solid-start-vite/src/routes/index.jsx | 21 ++- integration/apps/solid-vite/package.json | 4 +- .../apps/solid-vite/src/app-icons/.gitignore | 2 + .../apps/solid-vite/src/app-icons/index.d.ts | 1 + .../apps/solid-vite/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 21 ++- integration/apps/solid-vite/src/main.jsx | 21 ++- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../solid-vite/src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/solid-vite/src/style.css | 3 +- integration/apps/solid-webpack/package.json | 4 +- .../solid-webpack/src/app-icons/.gitignore | 2 + .../solid-webpack/src/app-icons/index.d.ts | 1 + .../apps/solid-webpack/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 21 ++- integration/apps/solid-webpack/src/main.jsx | 19 +- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 8 + .../cases/http-only/svg-sprite.config.js | 17 ++ .../cases/mixed-input/svg-sprite.config.js | 13 ++ .../transforms-disabled/svg-sprite.config.js | 11 ++ .../apps/standalone-server/package.json | 15 ++ .../apps/standalone-server/verify-release.mjs | 59 +++++++ integration/apps/standalone-vite/package.json | 4 +- .../standalone-vite/src/app-icons/.gitignore | 2 + .../standalone-vite/src/app-icons/index.ts | 9 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 16 +- integration/apps/standalone-vite/src/main.ts | 31 +++- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.ts | 9 + .../src/remote-app-icons/svg-sprite.config.js | 8 + .../apps/standalone-vite/src/sprite/index.ts | 9 - .../apps/standalone-vite/src/style.css | 3 +- .../apps/standalone-webpack/package.json | 4 +- .../src/app-icons/.gitignore | 2 + .../standalone-webpack/src/app-icons/index.ts | 9 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 16 +- .../apps/standalone-webpack/src/main.ts | 32 +++- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.ts | 9 + .../src/remote-app-icons/svg-sprite.config.js | 8 + .../standalone-webpack/src/sprite/index.ts | 9 - integration/apps/standalone/build.mjs | 22 ++- integration/apps/standalone/index.html | 16 +- integration/apps/standalone/package.json | 4 +- .../svg-sprite.config.json | 2 +- .../src/remote-app-icons/svg-sprite.config.js | 8 + integration/apps/svelte-vite/package.json | 4 +- integration/apps/svelte-vite/src/App.svelte | 17 +- .../apps/svelte-vite/src/app-icons/.gitignore | 2 + .../apps/svelte-vite/src/app-icons/index.d.ts | 1 + .../apps/svelte-vite/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../svelte-vite/src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 7 + .../apps/svelte-vite/src/type-probe.ts | 20 ++- integration/apps/svelte-webpack/package.json | 4 +- .../apps/svelte-webpack/src/App.svelte | 17 +- .../svelte-webpack/src/app-icons/.gitignore | 2 + .../svelte-webpack/src/app-icons/index.d.ts | 1 + .../svelte-webpack/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 7 + .../apps/svelte-webpack/src/type-probe.ts | 21 ++- integration/apps/sveltekit/package.json | 4 +- .../apps/sveltekit/src/app-icons/.gitignore | 2 + .../apps/sveltekit/src/app-icons/index.d.ts | 1 + .../apps/sveltekit/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../sveltekit/src/remote-app-icons/.gitignore | 2 + .../sveltekit/src/remote-app-icons/index.d.ts | 1 + .../sveltekit/src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 7 + .../apps/sveltekit/src/routes/+page.svelte | 17 +- integration/apps/sveltekit/src/type-probe.ts | 20 ++- integration/apps/vue-vite/package.json | 4 +- integration/apps/vue-vite/src/App.vue | 17 +- .../apps/vue-vite/src/app-icons/.gitignore | 2 + .../apps/vue-vite/src/app-icons/index.d.ts | 1 + .../apps/vue-vite/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 27 ++- .../vue-vite/src/remote-app-icons/.gitignore | 2 + .../vue-vite/src/remote-app-icons/index.d.ts | 1 + .../vue-vite/src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/apps/vue-webpack/package.json | 4 +- integration/apps/vue-webpack/src/App.vue | 17 +- .../apps/vue-webpack/src/app-icons/.gitignore | 2 + .../apps/vue-webpack/src/app-icons/index.d.ts | 1 + .../apps/vue-webpack/src/app-icons/index.js | 1 + .../svg-sprite.config.ts | 2 +- .../src/generated-contract.typecheck.ts | 27 ++- .../src/remote-app-icons/.gitignore | 2 + .../src/remote-app-icons/index.d.ts | 1 + .../vue-webpack/src/remote-app-icons/index.js | 1 + .../src/remote-app-icons/svg-sprite.config.js | 6 + integration/package-lock.json | 13 +- integration/package.json | 2 +- integration/scripts/apps.mjs | 2 +- integration/scripts/generate-sprites.mjs | 79 +++++++++ integration/tests/apps.spec.ts | 52 ++++-- skills/svg-sprites/skill.config.mjs | 4 +- skills/svg-sprites/src/en/SKILL.md | 38 +++- skills/svg-sprites/src/ru/SKILL.md | 38 +++- src/cli/parse-args.ts | 29 +++- src/compiler.ts | 28 ++- src/config.ts | 114 +++++++++--- src/core/mode-adapter.ts | 22 ++- src/core/prepare-sprite.ts | 12 +- src/core/resolve-compiled-artifact.ts | 25 +++ src/generate.ts | 22 ++- src/index.ts | 13 +- src/mode-registry.ts | 2 + src/modes/alpine-vite/adapter.ts | 12 +- src/modes/alpine-webpack/adapter.ts | 12 +- src/modes/angular-application/adapter.ts | 8 +- src/modes/angular-application/output.ts | 17 +- src/modes/angular-webpack/adapter.ts | 8 +- src/modes/astro-vite/adapter.ts | 8 +- src/modes/lit-vite/adapter.ts | 12 +- src/modes/lit-webpack/adapter.ts | 12 +- src/modes/next-app-turbopack/adapter.ts | 12 +- src/modes/next-app-webpack/adapter.ts | 10 +- src/modes/next-pages-turbopack/adapter.ts | 10 +- src/modes/next-pages-webpack/adapter.ts | 10 +- src/modes/nuxt-vite/adapter.ts | 12 +- src/modes/nuxt-webpack/adapter.ts | 12 +- src/modes/preact-vite/adapter.ts | 12 +- src/modes/preact-webpack/adapter.ts | 12 +- src/modes/qwik-vite/adapter.ts | 12 +- src/modes/react-vite/adapter.ts | 8 +- src/modes/react-webpack/adapter.ts | 12 +- src/modes/solid-start-vite/adapter.ts | 12 +- src/modes/solid-vite/adapter.ts | 12 +- src/modes/solid-webpack/adapter.ts | 12 +- src/modes/standalone-server/adapter.ts | 43 +++++ src/modes/standalone-server/output.ts | 69 ++++++++ src/modes/standalone-server/source.ts | 90 ++++++++++ src/modes/standalone-vite/adapter.ts | 12 +- src/modes/standalone-webpack/adapter.ts | 12 +- src/modes/standalone/adapter.ts | 12 +- src/modes/svelte-vite/adapter.ts | 8 +- src/modes/svelte-webpack/adapter.ts | 8 +- src/modes/sveltekit-vite/adapter.ts | 8 +- src/modes/vue-vite/adapter.ts | 8 +- src/modes/vue-webpack/adapter.ts | 12 +- src/release/load.ts | 164 ++++++++++++++++++ src/release/types.ts | 26 +++ src/targets/types.ts | 9 +- src/types.ts | 20 ++- test/angular-astro-mode-contracts.test.mjs | 5 +- test/documentation-guides.test.mjs | 19 +- test/server-remote-mode.test.mjs | 146 ++++++++++++++++ 379 files changed, 3108 insertions(+), 655 deletions(-) create mode 100644 docs/en/guides/standalone-server.md create mode 100644 docs/ru/guides/standalone-server.md rename integration/apps/alpine-vite/src/{sprite => app-icons}/.gitignore (100%) rename integration/apps/alpine-vite/src/{sprite => app-icons}/index.d.ts (100%) rename integration/apps/alpine-vite/src/{sprite => app-icons}/index.js (100%) rename integration/apps/alpine-vite/src/{sprite => app-icons}/svg-sprite.config.json (84%) rename integration/apps/{alpine-webpack/src/sprite => alpine-vite/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{alpine-webpack/src/sprite => alpine-vite/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{alpine-webpack/src/sprite => alpine-vite/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/alpine-vite/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{angular-webpack/src/sprite => alpine-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/{astro/src/sprite => alpine-webpack/src/app-icons}/index.d.ts (100%) rename integration/apps/{astro/src/sprite => alpine-webpack/src/app-icons}/index.js (100%) rename integration/apps/alpine-webpack/src/{sprite => app-icons}/svg-sprite.config.json (85%) rename integration/apps/{angular/src/sprite => alpine-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{lit-vite/src/sprite => alpine-webpack/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{lit-vite/src/sprite => alpine-webpack/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/alpine-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{astro/src/sprite => angular-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/angular-webpack/src/{sprite => app-icons}/index.ts (100%) rename integration/apps/angular-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (87%) rename integration/apps/{lit-vite/src/sprite => angular-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{angular/src/sprite => angular-webpack/src/remote-app-icons}/index.ts (100%) create mode 100644 integration/apps/angular-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{lit-webpack/src/sprite => angular/src/app-icons}/.gitignore (100%) create mode 100644 integration/apps/angular/src/app-icons/index.ts rename integration/apps/angular/src/{sprite => app-icons}/svg-sprite.config.ts (88%) rename integration/apps/{next-app-turbopack/src/sprite => angular/src/remote-app-icons}/.gitignore (100%) create mode 100644 integration/apps/angular/src/remote-app-icons/index.ts create mode 100644 integration/apps/angular/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{next-app-webpack/src/sprite => astro/src/app-icons}/.gitignore (100%) rename integration/apps/{lit-webpack/src/sprite => astro/src/app-icons}/index.d.ts (100%) rename integration/apps/{lit-webpack/src/sprite => astro/src/app-icons}/index.js (100%) rename integration/apps/astro/src/{sprite => app-icons}/svg-sprite.config.ts (87%) rename integration/apps/{next-pages-turbopack/src/sprite => astro/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{nuxt-vite/src/sprite => astro/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{nuxt-vite/src/sprite => astro/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/astro/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{next-pages-webpack/src/sprite => lit-vite/src/app-icons}/.gitignore (100%) rename integration/apps/{nuxt-webpack/src/sprite => lit-vite/src/app-icons}/index.d.ts (100%) rename integration/apps/{nuxt-webpack/src/sprite => lit-vite/src/app-icons}/index.js (100%) rename integration/apps/lit-vite/src/{sprite => app-icons}/svg-sprite.config.json (84%) rename integration/apps/{nuxt-vite/src/sprite => lit-vite/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{preact-vite/src/sprite => lit-vite/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{preact-vite/src/sprite => lit-vite/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/lit-vite/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{nuxt-webpack/src/sprite => lit-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/{preact-webpack/src/sprite => lit-webpack/src/app-icons}/index.d.ts (100%) rename integration/apps/{preact-webpack/src/sprite => lit-webpack/src/app-icons}/index.js (100%) rename integration/apps/lit-webpack/src/{sprite => app-icons}/svg-sprite.config.json (84%) rename integration/apps/{preact-vite/src/sprite => lit-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{qwik-vite/src/sprite => lit-webpack/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{solid-webpack/src/sprite => lit-webpack/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/lit-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{preact-webpack/src/sprite => next-app-turbopack/src/app-icons}/.gitignore (100%) rename integration/apps/next-app-turbopack/src/{sprite => app-icons}/index.ts (100%) rename integration/apps/next-app-turbopack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{qwik-vite/src/sprite => next-app-turbopack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{next-app-webpack/src/sprite => next-app-turbopack/src/remote-app-icons}/index.ts (100%) create mode 100644 integration/apps/next-app-turbopack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{react-vite/src/sprite => next-app-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/{next-pages-turbopack/src/sprite => next-app-webpack/src/app-icons}/index.ts (100%) rename integration/apps/next-app-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{react-webpack/src/sprite => next-app-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{next-pages-webpack/src/sprite => next-app-webpack/src/remote-app-icons}/index.ts (100%) create mode 100644 integration/apps/next-app-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{solid-start-vite/src/sprite => next-pages-turbopack/src/app-icons}/.gitignore (100%) rename integration/apps/{react-vite/src/sprite => next-pages-turbopack/src/app-icons}/index.ts (100%) rename integration/apps/next-pages-turbopack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{solid-vite/src/sprite => next-pages-turbopack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{react-webpack/src/sprite => next-pages-turbopack/src/remote-app-icons}/index.ts (100%) create mode 100644 integration/apps/next-pages-turbopack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{solid-webpack/src/sprite => next-pages-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/{qwik-vite/src/sprite/index.js => next-pages-webpack/src/app-icons/index.ts} (100%) rename integration/apps/next-pages-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{standalone-vite/src/sprite => next-pages-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{solid-start-vite/src/sprite/index.js => next-pages-webpack/src/remote-app-icons/index.ts} (100%) create mode 100644 integration/apps/next-pages-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{standalone-webpack/src/sprite => nuxt-vite/src/app-icons}/.gitignore (100%) rename integration/apps/{solid-start-vite/src/sprite => nuxt-vite/src/app-icons}/index.d.ts (100%) rename integration/apps/{svelte-vite/src/sprite => nuxt-vite/src/app-icons}/index.js (100%) rename integration/apps/nuxt-vite/src/{sprite => app-icons}/svg-sprite.config.ts (91%) rename integration/apps/{svelte-vite/src/sprite => nuxt-vite/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{solid-vite/src/sprite => nuxt-vite/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{svelte-webpack/src/sprite => nuxt-vite/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/nuxt-vite/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{svelte-webpack/src/sprite => nuxt-webpack/src/app-icons}/.gitignore (100%) rename integration/apps/{solid-webpack/src/sprite => nuxt-webpack/src/app-icons}/index.d.ts (100%) rename integration/apps/{sveltekit/src/sprite => nuxt-webpack/src/app-icons}/index.js (100%) rename integration/apps/nuxt-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{sveltekit/src/sprite => nuxt-webpack/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{svelte-vite/src/sprite => nuxt-webpack/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{vue-webpack/src/sprite => nuxt-webpack/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/nuxt-webpack/src/remote-app-icons/svg-sprite.config.js rename integration/apps/{vue-vite/src/sprite => preact-vite/src/app-icons}/.gitignore (100%) rename integration/apps/{svelte-webpack/src/sprite => preact-vite/src/app-icons}/index.d.ts (100%) rename integration/apps/{sveltekit/src/sprite/index.d.ts => preact-vite/src/app-icons/index.js} (100%) rename integration/apps/preact-vite/src/{sprite => app-icons}/svg-sprite.config.ts (92%) rename integration/apps/{vue-webpack/src/sprite => preact-vite/src/remote-app-icons}/.gitignore (100%) rename integration/apps/{vue-vite/src/sprite => preact-vite/src/remote-app-icons}/index.d.ts (100%) rename integration/apps/{vue-webpack/src/sprite/index.d.ts => preact-vite/src/remote-app-icons/index.js} (100%) create mode 100644 integration/apps/preact-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/preact-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/preact-webpack/src/app-icons/index.d.ts create mode 100644 integration/apps/preact-webpack/src/app-icons/index.js rename integration/apps/preact-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/preact-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/preact-webpack/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/preact-webpack/src/remote-app-icons/index.js create mode 100644 integration/apps/preact-webpack/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/qwik-vite/src/app-icons/.gitignore create mode 100644 integration/apps/qwik-vite/src/app-icons/index.d.ts rename integration/apps/{solid-vite/src/sprite => qwik-vite/src/app-icons}/index.js (100%) rename integration/apps/qwik-vite/src/{sprite => app-icons}/svg-sprite.config.ts (91%) create mode 100644 integration/apps/qwik-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/qwik-vite/src/remote-app-icons/index.d.ts rename integration/apps/{vue-vite/src/sprite => qwik-vite/src/remote-app-icons}/index.js (100%) create mode 100644 integration/apps/qwik-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/react-vite/src/app-icons/.gitignore create mode 100644 integration/apps/react-vite/src/app-icons/index.ts rename integration/apps/react-vite/src/{sprite => app-icons}/svg-sprite.config.ts (91%) create mode 100644 integration/apps/react-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/react-vite/src/remote-app-icons/index.ts create mode 100644 integration/apps/react-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/react-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/react-webpack/src/app-icons/index.ts rename integration/apps/react-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/react-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/react-webpack/src/remote-app-icons/index.ts create mode 100644 integration/apps/react-webpack/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/solid-start-vite/src/app-icons/.gitignore create mode 100644 integration/apps/solid-start-vite/src/app-icons/index.d.ts create mode 100644 integration/apps/solid-start-vite/src/app-icons/index.js rename integration/apps/solid-start-vite/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/solid-start-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/solid-start-vite/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/solid-start-vite/src/remote-app-icons/index.js create mode 100644 integration/apps/solid-start-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/solid-vite/src/app-icons/.gitignore create mode 100644 integration/apps/solid-vite/src/app-icons/index.d.ts create mode 100644 integration/apps/solid-vite/src/app-icons/index.js rename integration/apps/solid-vite/src/{sprite => app-icons}/svg-sprite.config.ts (91%) create mode 100644 integration/apps/solid-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/solid-vite/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/solid-vite/src/remote-app-icons/index.js create mode 100644 integration/apps/solid-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/solid-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/solid-webpack/src/app-icons/index.d.ts create mode 100644 integration/apps/solid-webpack/src/app-icons/index.js rename integration/apps/solid-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/solid-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/solid-webpack/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/solid-webpack/src/remote-app-icons/index.js create mode 100644 integration/apps/solid-webpack/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/standalone-server/cases/http-only/svg-sprite.config.js create mode 100644 integration/apps/standalone-server/cases/mixed-input/svg-sprite.config.js create mode 100644 integration/apps/standalone-server/cases/transforms-disabled/svg-sprite.config.js create mode 100644 integration/apps/standalone-server/package.json create mode 100644 integration/apps/standalone-server/verify-release.mjs create mode 100644 integration/apps/standalone-vite/src/app-icons/.gitignore create mode 100644 integration/apps/standalone-vite/src/app-icons/index.ts rename integration/apps/standalone-vite/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/standalone-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/standalone-vite/src/remote-app-icons/index.ts create mode 100644 integration/apps/standalone-vite/src/remote-app-icons/svg-sprite.config.js delete mode 100644 integration/apps/standalone-vite/src/sprite/index.ts create mode 100644 integration/apps/standalone-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/standalone-webpack/src/app-icons/index.ts rename integration/apps/standalone-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/standalone-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/standalone-webpack/src/remote-app-icons/index.ts create mode 100644 integration/apps/standalone-webpack/src/remote-app-icons/svg-sprite.config.js delete mode 100644 integration/apps/standalone-webpack/src/sprite/index.ts rename integration/apps/standalone/src/{sprite => app-icons}/svg-sprite.config.json (82%) create mode 100644 integration/apps/standalone/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/svelte-vite/src/app-icons/.gitignore create mode 100644 integration/apps/svelte-vite/src/app-icons/index.d.ts create mode 100644 integration/apps/svelte-vite/src/app-icons/index.js rename integration/apps/svelte-vite/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/svelte-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/svelte-vite/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/svelte-vite/src/remote-app-icons/index.js create mode 100644 integration/apps/svelte-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/svelte-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/svelte-webpack/src/app-icons/index.d.ts create mode 100644 integration/apps/svelte-webpack/src/app-icons/index.js rename integration/apps/svelte-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/svelte-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/svelte-webpack/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/svelte-webpack/src/remote-app-icons/index.js create mode 100644 integration/apps/svelte-webpack/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/sveltekit/src/app-icons/.gitignore create mode 100644 integration/apps/sveltekit/src/app-icons/index.d.ts create mode 100644 integration/apps/sveltekit/src/app-icons/index.js rename integration/apps/sveltekit/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/sveltekit/src/remote-app-icons/.gitignore create mode 100644 integration/apps/sveltekit/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/sveltekit/src/remote-app-icons/index.js create mode 100644 integration/apps/sveltekit/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/vue-vite/src/app-icons/.gitignore create mode 100644 integration/apps/vue-vite/src/app-icons/index.d.ts create mode 100644 integration/apps/vue-vite/src/app-icons/index.js rename integration/apps/vue-vite/src/{sprite => app-icons}/svg-sprite.config.ts (91%) create mode 100644 integration/apps/vue-vite/src/remote-app-icons/.gitignore create mode 100644 integration/apps/vue-vite/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/vue-vite/src/remote-app-icons/index.js create mode 100644 integration/apps/vue-vite/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/apps/vue-webpack/src/app-icons/.gitignore create mode 100644 integration/apps/vue-webpack/src/app-icons/index.d.ts create mode 100644 integration/apps/vue-webpack/src/app-icons/index.js rename integration/apps/vue-webpack/src/{sprite => app-icons}/svg-sprite.config.ts (92%) create mode 100644 integration/apps/vue-webpack/src/remote-app-icons/.gitignore create mode 100644 integration/apps/vue-webpack/src/remote-app-icons/index.d.ts create mode 100644 integration/apps/vue-webpack/src/remote-app-icons/index.js create mode 100644 integration/apps/vue-webpack/src/remote-app-icons/svg-sprite.config.js create mode 100644 integration/scripts/generate-sprites.mjs create mode 100644 src/core/resolve-compiled-artifact.ts create mode 100644 src/modes/standalone-server/adapter.ts create mode 100644 src/modes/standalone-server/output.ts create mode 100644 src/modes/standalone-server/source.ts create mode 100644 src/release/load.ts create mode 100644 src/release/types.ts create mode 100644 test/server-remote-mode.test.mjs diff --git a/AGENTS.md b/AGENTS.md index 8fa0545..cff01ba 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,6 +13,7 @@ - `standalone`; - `standalone@vite`; - `standalone@webpack`; +- `standalone@server`; - `vue@vite`; - `vue@webpack`; - `nuxt@vite`; @@ -75,6 +76,8 @@ Core не генерирует JavaScript, declarations, manifest source, CSS или framework-specific exports. Изменение общего compiler может ожидаемо изменить SVG всех modes; изменение generated source должно быть локально одному adapter. +Mode-neutral инфраструктура также может загружать и проверять manifest и готовые SVG profiles, созданные `standalone@server`. Сетевой слой не генерирует framework output и передаёт adapter только проверенный compiled artifact. + ## Generated-контракт Один config разрешается ровно в один mode и один output. Множественные modes не генерируются в один root; orchestration выполняется независимыми config/API/CLI вызовами. @@ -87,6 +90,8 @@ Core writer полностью владеет каталогом `.svg-sprite` Sprite-level asset, icon data, manifest и facade лежат непосредственно в `.svg-sprite/`. `standalone@vite` и `standalone@webpack` генерируют нативный icon Web Component внутри своего facade; bare `standalone` остаётся без JavaScript runtime. Framework runtime группируется отдельно: React adapters используют `.svg-sprite/react/`, будущие framework adapters получают собственный framework-каталог. +`standalone@server` принимает local paths/globs и HTTP(S) descriptors `{ name, url, sha256? }`, создаёт content-addressed SVG profiles и JSON manifest. Он не создаёт consumer runtime или `.gitignore`. Consumer modes с `source: "remote"` скачивают один из этих profiles до codegen и по-прежнему публикуют SVG через собственный asset pipeline. + Adapter возвращает файлы в памяти. Только core writer проверяет paths, полностью заменяет `.svg-sprite` и обновляет управляемый `.gitignore`. ## Зависимости diff --git a/FEATURES.md b/FEATURES.md index 3a8ac00..3078877 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -42,7 +42,7 @@ `SpriteViewer` рендерит все спрайты проекта в одном месте и показывает, какие иконки вошли в каждый набор и как они выглядят. Для каждой иконки видны созданные CSS-переменные и их fallback-цвета. Значения можно менять прямо в Viewer и сразу наблюдать результат. Здесь же доступны готовые примеры для framework из manifest, ``, `` и CSS. -11. **29 exact modes** +11. **29 consumer exact modes и `standalone@server`** Изолированные adapters создают нативные компоненты для standalone, React, Next.js, Vue, Nuxt, Svelte, SvelteKit, Angular, Astro, Solid, SolidStart, Preact, Qwik, Lit и Alpine.js. Каждый exact mode учитывает свой Vite, Webpack, Turbopack или application-builder контракт. diff --git a/MODES_CHECKLIST.md b/MODES_CHECKLIST.md index ff0c2b1..2dbc699 100644 --- a/MODES_CHECKLIST.md +++ b/MODES_CHECKLIST.md @@ -14,6 +14,7 @@ Mode отмечается поддержанным только после за - [x] `standalone` - [x] `standalone@vite` - [x] `standalone@webpack` +- [x] `standalone@server` (server release + remote `react@vite` integration) ## React diff --git a/README.md b/README.md index e1365cf..c666323 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) -`@gromlab/svg-sprites` is an SVG sprite generator for modern web applications. It combines selected SVG icons into one or more external, cacheable sprites and prepares them for use in the UI. +`@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. @@ -217,9 +217,19 @@ The Viewer is added only to an internal debug page and does not become part of t 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`. -## 29 exact modes +## 30 exact modes -The package provides isolated contracts for 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. +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 @@ -237,7 +247,11 @@ Production components use only local generated code, styles, and the external SV This README introduces the project's capabilities and demonstrates the primary use case. For setup, choose the guide for your stack. -### Quick start +### 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) diff --git a/README_RU.md b/README_RU.md index e0122c4..b0eb0ea 100644 --- a/README_RU.md +++ b/README_RU.md @@ -4,7 +4,7 @@ ![npm](https://img.shields.io/npm/v/@gromlab/svg-sprites) ![license](https://img.shields.io/npm/l/@gromlab/svg-sprites) -`@gromlab/svg-sprites` — генератор SVG-спрайтов для современных веб-приложений. Он собирает выбранные SVG-иконки в один или несколько внешних кешируемых спрайтов и подготавливает их для использования в интерфейсе. +`@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. @@ -217,9 +217,19 @@ Viewer подключается только к внутренней debug-ст Bare standalone подключает Viewer через browser script и HTML element. Bundler и framework modes используют npm entry Web Component; React и Next.js также могут импортировать bridge из `@gromlab/svg-sprites/react`. -## 29 exact modes +## 30 exact modes -Пакет предоставляет изолированные контракты для standalone, React, Next.js, Vue, Nuxt, Svelte, SvelteKit, Angular, Astro, Solid, SolidStart, Preact, Qwik, Lit и Alpine.js в поддерживаемых вариантах Vite, Webpack, Turbopack и application builder. +Пакет поддерживает 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 @@ -237,7 +247,11 @@ Production-компоненты используют только локальн 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) diff --git a/docs/en/README.md b/docs/en/README.md index f319fb3..ec13211 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -5,7 +5,7 @@ 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). -## Quick Start Guides +## Consumer Quick Starts | Project | Exact mode | Guide | |---|---|---| @@ -39,12 +39,16 @@ The common format for JSON, JavaScript, and TypeScript config files is described | 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 guide follows the same order: +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) diff --git a/docs/en/configuration.md b/docs/en/configuration.md index 1c4e847..7752b73 100644 --- a/docs/en/configuration.md +++ b/docs/en/configuration.md @@ -32,6 +32,7 @@ JSON works for most projects and does not require installing the package locally | 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 | @@ -40,6 +41,45 @@ JSON works for most projects and does not require installing the package locally 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: diff --git a/docs/en/guides/README.md b/docs/en/guides/README.md index 3af8914..6284962 100644 --- a/docs/en/guides/README.md +++ b/docs/en/guides/README.md @@ -1,5 +1,7 @@ # Quick Start Guides +## Consumer Applications + - `standalone`: [bare standalone](standalone.md) - `standalone@vite`: [standalone with Vite](standalone-vite.md) - `standalone@webpack`: [standalone with Webpack](standalone-webpack.md) @@ -29,3 +31,7 @@ - `next@app/webpack`: [App Router with Webpack](next-app-webpack.md) - `next@pages/turbopack`: [Pages Router with Turbopack](next-pages-turbopack.md) - `next@pages/webpack`: [Pages Router with Webpack](next-pages-webpack.md) + +## Server-Side Generation + +- `standalone@server`: [generate a universal sprite on the server](standalone-server.md) diff --git a/docs/en/guides/standalone-server.md b/docs/en/guides/standalone-server.md new file mode 100644 index 0000000..4cc1058 --- /dev/null +++ b/docs/en/guides/standalone-server.md @@ -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..svg + ├── sprite-root-viewbox..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..svg +├── sprite-root-viewbox..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 +} +``` + +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. diff --git a/docs/en/reference/programmatic-api.md b/docs/en/reference/programmatic-api.md index a875156..14c1f52 100644 --- a/docs/en/reference/programmatic-api.md +++ b/docs/en/reference/programmatic-api.md @@ -30,7 +30,8 @@ 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. +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: @@ -105,6 +106,11 @@ export default defineSpriteConfig({ `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`: diff --git a/docs/en/reference/technical.md b/docs/en/reference/technical.md index 158e394..08c8e48 100644 --- a/docs/en/reference/technical.md +++ b/docs/en/reference/technical.md @@ -69,6 +69,7 @@ svg-sprites [options] | 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` | @@ -100,7 +101,7 @@ The config file may have any name and use the `.ts`, `.js`, or `.json` extension 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`, `--name`, `--description`, repeatable `--input `, 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. +`--help` and `-h` print usage information without requiring a path. Generation options are `--mode`, `--source `, `--name`, `--description`, repeatable `--input `, 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: @@ -138,12 +139,20 @@ export default defineSpriteConfig({ | 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` | `string \| string[]` | `./icons` | SVG folders, files, and glob patterns relative to the config directory | +| `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: @@ -176,6 +185,26 @@ Supported glob syntax includes: 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: @@ -225,6 +254,20 @@ runtime asset and deployment-neutral manifest data: 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..svg +├── sprite-root-viewbox..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 diff --git a/docs/ru/README.md b/docs/ru/README.md index 820c6c7..369e571 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -5,7 +5,7 @@ Общий формат JSON, JavaScript и TypeScript config-файлов описан в [руководстве по конфигурации](configuration.md). -## Гайды быстрого старта +## Быстрый старт для consumer modes | Проект | Exact mode | Guide | |---|---|---| @@ -39,12 +39,16 @@ | 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) | -Все guides используют один порядок: +Все consumer guides используют один порядок: 1. Генерация спрайта через `npx` без добавления package в проект. 2. Использование спрайта в приложении. 3. Необязательное подключение Viewer для дебага и превью. +## Серверная генерация + +Используйте [`standalone@server`](guides/standalone-server.md), чтобы сгенерировать на сервере или в CI/CD универсальный SVG-спрайт для всех consumer modes. + ## Справочники - [Конфигурация](configuration.md) diff --git a/docs/ru/configuration.md b/docs/ru/configuration.md index 2a16704..4d8c77c 100644 --- a/docs/ru/configuration.md +++ b/docs/ru/configuration.md @@ -32,6 +32,7 @@ JSON подходит для большинства проектов и не т | Поле | По умолчанию | Назначение | |---|---|---| | `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-шаблон или массив источников | @@ -40,6 +41,45 @@ JSON подходит для большинства проектов и не т Пути и 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-конфиг экспортирует обычный объект по умолчанию: diff --git a/docs/ru/guides/AGENTS.md b/docs/ru/guides/AGENTS.md index 472147f..fbec250 100644 --- a/docs/ru/guides/AGENTS.md +++ b/docs/ru/guides/AGENTS.md @@ -30,13 +30,19 @@ Пути, имена, команды, импорты и названия сгенерированных API должны соответствовать друг другу и фактическому результату генерации. -Во всех гайдах используются согласованные примеры: +Во всех consumer-гайдах используются согласованные примеры: - исходные SVG находятся в `assets/svg-icons`; - спрайт создаётся в `assets/app-icons`; - конфиг записывается в JSON; - имя спрайта в конфиге — `app`. +`standalone@server` является исключением: quick start использует config-less CLI, +исходные SVG находятся в `./icons` временного worker workspace, output создаётся в +текущем каталоге, а mode, name и input передаются флагами одной команды. Server +config упоминается только как дополнительный вариант; подключение из consumer +может использовать обычный JSON config соответствующего mode. + ## Зависимости В разделе генерации нужно явно показать ключевое преимущество: для создания и использования спрайта пакет не требуется добавлять в зависимости проекта. @@ -48,7 +54,7 @@ Viewer описывается отдельно как необязательны Гайд должен содержать только минимальный рабочий путь: - структуру проекта; -- конфиг; +- конфиг либо полный config-less CLI-вызов для `standalone@server`; - команду генерации; - автоматическую генерацию перед запуском и сборкой, если она необходима; - подключение иконки; diff --git a/docs/ru/guides/README.md b/docs/ru/guides/README.md index 4cf1a7c..b968244 100644 --- a/docs/ru/guides/README.md +++ b/docs/ru/guides/README.md @@ -1,5 +1,7 @@ # Гайды быстрого старта +## Consumer-приложения + - `standalone`: [bare standalone](standalone.md) - `standalone@vite`: [standalone с Vite](standalone-vite.md) - `standalone@webpack`: [standalone с Webpack](standalone-webpack.md) @@ -29,3 +31,7 @@ - `next@app/webpack`: [App Router с Webpack](next-app-webpack.md) - `next@pages/turbopack`: [Pages Router с Turbopack](next-pages-turbopack.md) - `next@pages/webpack`: [Pages Router с Webpack](next-pages-webpack.md) + +## Серверная генерация + +- `standalone@server`: [сгенерировать универсальный спрайт на сервере](standalone-server.md) diff --git a/docs/ru/guides/standalone-server.md b/docs/ru/guides/standalone-server.md new file mode 100644 index 0000000..0941967 --- /dev/null +++ b/docs/ru/guides/standalone-server.md @@ -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..svg + ├── sprite-root-viewbox..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..svg +├── sprite-root-viewbox..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 +} +``` + +Тот же CDN manifest поддерживают все 29 consumer modes. В каждом из них сохраняется нативный API выбранного framework и bundler. + +## Дебаг и превью + +`standalone@server` не создаёт отдельную страницу для просмотра иконок. Подключите опубликованный спрайт к consumer-приложению и откройте его в SpriteViewer: удалённый набор будет отображаться так же, как локальный. diff --git a/docs/ru/reference/programmatic-api.md b/docs/ru/reference/programmatic-api.md index 3a644b2..8c06a79 100644 --- a/docs/ru/reference/programmatic-api.md +++ b/docs/ru/reference/programmatic-api.md @@ -27,7 +27,9 @@ result.spritePath result.manifestPath ``` -Next.js modes дополнительно возвращают `router` и `bundler`. +Next.js modes дополнительно возвращают `router` и `bundler`. `standalone@server` +возвращает `target: 'server'`; его `spritePath` указывает на стандартный +content-addressed profile, а `manifestPath` — на server manifest. Для static standalone mode `result.spritePath` можно использовать в build-скрипте, чтобы опубликовать SVG по URL приложения: @@ -102,6 +104,11 @@ export default defineSpriteConfig({ `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`: diff --git a/docs/ru/reference/technical.md b/docs/ru/reference/technical.md index 179d03e..b9957e6 100644 --- a/docs/ru/reference/technical.md +++ b/docs/ru/reference/technical.md @@ -69,6 +69,7 @@ svg-sprites [options] | 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` | @@ -100,7 +101,7 @@ Config-файл может иметь любое имя и расширение Если передан каталог, все настройки берутся из CLI. Если передан config-файл, CLI-параметры перекрывают значения файла. Общий порядок: `defaults → config → CLI`. -`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--name`, `--description`, повторяемый `--input `, а также пары `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition` и `--generated-notice`/`--no-generated-notice`. Переданные transform-флаги перекрывают отдельные поля, а хотя бы один `--input` полностью заменяет значение `input` из config. +`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--source `, `--name`, `--description`, повторяемый `--input `, а также пары `--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 не раскрыл их до запуска генератора: @@ -138,12 +139,20 @@ export default defineSpriteConfig({ | Опция | Тип | По умолчанию | Назначение | |---|---|---|---| | `mode` | `SpriteMode` | Нет | Режим генерации; можно передать через CLI/API | +| `source` | `local \| remote` | `local` | Исходные SVG либо готовый server manifest | | `name` | `string` | Выводится из каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и публичных типов | | `description` | `string` | Нет | Описание для типов и debug manifest | -| `input` | `string \| string[]` | `./icons` | Папки, SVG-файлы и glob-паттерны относительно папки конфига | +| `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 и должно начинаться с латинской буквы: @@ -176,6 +185,26 @@ file-manager → FileManagerIcon Каждый включающий источник или паттерн должен найти хотя бы один 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-каталог спрайта выглядит так: @@ -225,6 +254,20 @@ runtime asset и deployment-neutral manifest data: generated Web Component без внешних runtime-зависимостей. Bare `standalone` намеренно не создаёт JavaScript-компонент. +`standalone@server` создаёт готовый к публикации release без JavaScript runtime и +`.gitignore`: + +```text +.svg-sprite/ +├── sprite..svg +├── sprite-root-viewbox..svg +└── svg-sprite.manifest.json +``` + +Manifest описывает оба compile profiles через relative `href`, полный SHA-256 и +размер в байтах. Публикуйте весь каталог атомарно; consumer разрешает каждый profile +относительно URL или local path manifest. + `.svg-sprite` полностью управляется генератором и при каждой генерации заменяется целиком. Любые добавленные в него файлы будут удалены. Пользовательские файлы размещайте рядом, например в корневом `index.ts`: ```ts diff --git a/integration/.gitignore b/integration/.gitignore index 3680986..00893c8 100644 --- a/integration/.gitignore +++ b/integration/.gitignore @@ -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/ diff --git a/integration/README.md b/integration/README.md index e581a1c..1f440d5 100644 --- a/integration/README.md +++ b/integration/README.md @@ -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 ``. diff --git a/integration/apps/alpine-vite/package.json b/integration/apps/alpine-vite/package.json index a2e3dfa..594e1b8 100644 --- a/integration/apps/alpine-vite/package.json +++ b/integration/apps/alpine-vite/package.json @@ -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" diff --git a/integration/apps/alpine-vite/src/sprite/.gitignore b/integration/apps/alpine-vite/src/app-icons/.gitignore similarity index 100% rename from integration/apps/alpine-vite/src/sprite/.gitignore rename to integration/apps/alpine-vite/src/app-icons/.gitignore diff --git a/integration/apps/alpine-vite/src/sprite/index.d.ts b/integration/apps/alpine-vite/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/alpine-vite/src/sprite/index.d.ts rename to integration/apps/alpine-vite/src/app-icons/index.d.ts diff --git a/integration/apps/alpine-vite/src/sprite/index.js b/integration/apps/alpine-vite/src/app-icons/index.js similarity index 100% rename from integration/apps/alpine-vite/src/sprite/index.js rename to integration/apps/alpine-vite/src/app-icons/index.js diff --git a/integration/apps/alpine-vite/src/sprite/svg-sprite.config.json b/integration/apps/alpine-vite/src/app-icons/svg-sprite.config.json similarity index 84% rename from integration/apps/alpine-vite/src/sprite/svg-sprite.config.json rename to integration/apps/alpine-vite/src/app-icons/svg-sprite.config.json index ac49208..7ce2eeb 100644 --- a/integration/apps/alpine-vite/src/sprite/svg-sprite.config.json +++ b/integration/apps/alpine-vite/src/app-icons/svg-sprite.config.json @@ -1,6 +1,6 @@ { "mode": "alpine@vite", - "name": "icons", + "name": "app", "input": "../../../../fixtures/icons/check.svg", "generatedNotice": false } diff --git a/integration/apps/alpine-vite/src/generated-contract.typecheck.ts b/integration/apps/alpine-vite/src/generated-contract.typecheck.ts index 5df6ec7..807ba76 100644 --- a/integration/apps/alpine-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/alpine-vite/src/generated-contract.typecheck.ts @@ -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 diff --git a/integration/apps/alpine-vite/src/main.js b/integration/apps/alpine-vite/src/main.js index c3da3d4..3925df1 100644 --- a/integration/apps/alpine-vite/src/main.js +++ b/integration/apps/alpine-vite/src/main.js @@ -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 = ` + ` -document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest] +document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest] Alpine.start() diff --git a/integration/apps/alpine-webpack/src/sprite/.gitignore b/integration/apps/alpine-vite/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/alpine-webpack/src/sprite/.gitignore rename to integration/apps/alpine-vite/src/remote-app-icons/.gitignore diff --git a/integration/apps/alpine-webpack/src/sprite/index.d.ts b/integration/apps/alpine-vite/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/alpine-webpack/src/sprite/index.d.ts rename to integration/apps/alpine-vite/src/remote-app-icons/index.d.ts diff --git a/integration/apps/alpine-webpack/src/sprite/index.js b/integration/apps/alpine-vite/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/alpine-webpack/src/sprite/index.js rename to integration/apps/alpine-vite/src/remote-app-icons/index.js diff --git a/integration/apps/alpine-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/alpine-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..848541f --- /dev/null +++ b/integration/apps/alpine-vite/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/alpine-webpack/package.json b/integration/apps/alpine-webpack/package.json index c6a363d..7c38b13 100644 --- a/integration/apps/alpine-webpack/package.json +++ b/integration/apps/alpine-webpack/package.json @@ -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" diff --git a/integration/apps/angular-webpack/src/sprite/.gitignore b/integration/apps/alpine-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/angular-webpack/src/sprite/.gitignore rename to integration/apps/alpine-webpack/src/app-icons/.gitignore diff --git a/integration/apps/astro/src/sprite/index.d.ts b/integration/apps/alpine-webpack/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/astro/src/sprite/index.d.ts rename to integration/apps/alpine-webpack/src/app-icons/index.d.ts diff --git a/integration/apps/astro/src/sprite/index.js b/integration/apps/alpine-webpack/src/app-icons/index.js similarity index 100% rename from integration/apps/astro/src/sprite/index.js rename to integration/apps/alpine-webpack/src/app-icons/index.js diff --git a/integration/apps/alpine-webpack/src/sprite/svg-sprite.config.json b/integration/apps/alpine-webpack/src/app-icons/svg-sprite.config.json similarity index 85% rename from integration/apps/alpine-webpack/src/sprite/svg-sprite.config.json rename to integration/apps/alpine-webpack/src/app-icons/svg-sprite.config.json index 022defc..16df006 100644 --- a/integration/apps/alpine-webpack/src/sprite/svg-sprite.config.json +++ b/integration/apps/alpine-webpack/src/app-icons/svg-sprite.config.json @@ -1,6 +1,6 @@ { "mode": "alpine@webpack", - "name": "icons", + "name": "app", "input": "../../../../fixtures/icons/check.svg", "generatedNotice": false } diff --git a/integration/apps/alpine-webpack/src/generated-contract.typecheck.ts b/integration/apps/alpine-webpack/src/generated-contract.typecheck.ts index 5df6ec7..807ba76 100644 --- a/integration/apps/alpine-webpack/src/generated-contract.typecheck.ts +++ b/integration/apps/alpine-webpack/src/generated-contract.typecheck.ts @@ -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 diff --git a/integration/apps/alpine-webpack/src/main.js b/integration/apps/alpine-webpack/src/main.js index 78a4e41..f1912c2 100644 --- a/integration/apps/alpine-webpack/src/main.js +++ b/integration/apps/alpine-webpack/src/main.js @@ -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 = ` + ` -document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest] +document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest] Alpine.start() diff --git a/integration/apps/angular/src/sprite/.gitignore b/integration/apps/alpine-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/angular/src/sprite/.gitignore rename to integration/apps/alpine-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/lit-vite/src/sprite/index.d.ts b/integration/apps/alpine-webpack/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/lit-vite/src/sprite/index.d.ts rename to integration/apps/alpine-webpack/src/remote-app-icons/index.d.ts diff --git a/integration/apps/lit-vite/src/sprite/index.js b/integration/apps/alpine-webpack/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/lit-vite/src/sprite/index.js rename to integration/apps/alpine-webpack/src/remote-app-icons/index.js diff --git a/integration/apps/alpine-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/alpine-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..bd1693a --- /dev/null +++ b/integration/apps/alpine-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/angular-webpack/package.json b/integration/apps/angular-webpack/package.json index 891bb0b..951358f 100644 --- a/integration/apps/angular-webpack/package.json +++ b/integration/apps/angular-webpack/package.json @@ -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" diff --git a/integration/apps/astro/src/sprite/.gitignore b/integration/apps/angular-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/astro/src/sprite/.gitignore rename to integration/apps/angular-webpack/src/app-icons/.gitignore diff --git a/integration/apps/angular-webpack/src/sprite/index.ts b/integration/apps/angular-webpack/src/app-icons/index.ts similarity index 100% rename from integration/apps/angular-webpack/src/sprite/index.ts rename to integration/apps/angular-webpack/src/app-icons/index.ts diff --git a/integration/apps/angular-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/angular-webpack/src/app-icons/svg-sprite.config.ts similarity index 87% rename from integration/apps/angular-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/angular-webpack/src/app-icons/svg-sprite.config.ts index 4384bc5..9eb445e 100644 --- a/integration/apps/angular-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/angular-webpack/src/app-icons/svg-sprite.config.ts @@ -1,6 +1,6 @@ export default { mode: 'angular@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, } diff --git a/integration/apps/angular-webpack/src/main.ts b/integration/apps/angular-webpack/src/main.ts index a9fe7d0..6023ed4 100644 --- a/integration/apps/angular-webpack/src/main.ts +++ b/integration/apps/angular-webpack/src/main.ts @@ -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: `

Angular + Webpack

- + 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'), ] } diff --git a/integration/apps/lit-vite/src/sprite/.gitignore b/integration/apps/angular-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/lit-vite/src/sprite/.gitignore rename to integration/apps/angular-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/angular/src/sprite/index.ts b/integration/apps/angular-webpack/src/remote-app-icons/index.ts similarity index 100% rename from integration/apps/angular/src/sprite/index.ts rename to integration/apps/angular-webpack/src/remote-app-icons/index.ts diff --git a/integration/apps/angular-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/angular-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..488275e --- /dev/null +++ b/integration/apps/angular-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/angular-webpack/src/type-probe.ts b/integration/apps/angular-webpack/src/type-probe.ts index 32854b2..3b217e4 100644 --- a/integration/apps/angular-webpack/src/type-probe.ts +++ b/integration/apps/angular-webpack/src/type-probe.ts @@ -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 diff --git a/integration/apps/angular/package.json b/integration/apps/angular/package.json index 972f7cc..07dc376 100644 --- a/integration/apps/angular/package.json +++ b/integration/apps/angular/package.json @@ -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" diff --git a/integration/apps/lit-webpack/src/sprite/.gitignore b/integration/apps/angular/src/app-icons/.gitignore similarity index 100% rename from integration/apps/lit-webpack/src/sprite/.gitignore rename to integration/apps/angular/src/app-icons/.gitignore diff --git a/integration/apps/angular/src/app-icons/index.ts b/integration/apps/angular/src/app-icons/index.ts new file mode 100644 index 0000000..26b8ed7 --- /dev/null +++ b/integration/apps/angular/src/app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index' diff --git a/integration/apps/angular/src/sprite/svg-sprite.config.ts b/integration/apps/angular/src/app-icons/svg-sprite.config.ts similarity index 88% rename from integration/apps/angular/src/sprite/svg-sprite.config.ts rename to integration/apps/angular/src/app-icons/svg-sprite.config.ts index 1481e0e..9bb0b5f 100644 --- a/integration/apps/angular/src/sprite/svg-sprite.config.ts +++ b/integration/apps/angular/src/app-icons/svg-sprite.config.ts @@ -1,6 +1,6 @@ export default { mode: 'angular@application', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, } diff --git a/integration/apps/angular/src/app.component.ts b/integration/apps/angular/src/app.component.ts index e70f220..20c1603 100644 --- a/integration/apps/angular/src/app.component.ts +++ b/integration/apps/angular/src/app.component.ts @@ -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: `

Angular application builder

- + 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'), ] } diff --git a/integration/apps/next-app-turbopack/src/sprite/.gitignore b/integration/apps/angular/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/next-app-turbopack/src/sprite/.gitignore rename to integration/apps/angular/src/remote-app-icons/.gitignore diff --git a/integration/apps/angular/src/remote-app-icons/index.ts b/integration/apps/angular/src/remote-app-icons/index.ts new file mode 100644 index 0000000..26b8ed7 --- /dev/null +++ b/integration/apps/angular/src/remote-app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index' diff --git a/integration/apps/angular/src/remote-app-icons/svg-sprite.config.js b/integration/apps/angular/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..3b04c2f --- /dev/null +++ b/integration/apps/angular/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/angular/src/styles.css b/integration/apps/angular/src/styles.css index 5f94093..4b72f9d 100644 --- a/integration/apps/angular/src/styles.css +++ b/integration/apps/angular/src/styles.css @@ -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; diff --git a/integration/apps/angular/src/type-probe.ts b/integration/apps/angular/src/type-probe.ts index a50f31d..ed152fc 100644 --- a/integration/apps/angular/src/type-probe.ts +++ b/integration/apps/angular/src/type-probe.ts @@ -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 } diff --git a/integration/apps/astro/package.json b/integration/apps/astro/package.json index ee8f215..a9edfbd 100644 --- a/integration/apps/astro/package.json +++ b/integration/apps/astro/package.json @@ -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" diff --git a/integration/apps/next-app-webpack/src/sprite/.gitignore b/integration/apps/astro/src/app-icons/.gitignore similarity index 100% rename from integration/apps/next-app-webpack/src/sprite/.gitignore rename to integration/apps/astro/src/app-icons/.gitignore diff --git a/integration/apps/lit-webpack/src/sprite/index.d.ts b/integration/apps/astro/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/lit-webpack/src/sprite/index.d.ts rename to integration/apps/astro/src/app-icons/index.d.ts diff --git a/integration/apps/lit-webpack/src/sprite/index.js b/integration/apps/astro/src/app-icons/index.js similarity index 100% rename from integration/apps/lit-webpack/src/sprite/index.js rename to integration/apps/astro/src/app-icons/index.js diff --git a/integration/apps/astro/src/sprite/svg-sprite.config.ts b/integration/apps/astro/src/app-icons/svg-sprite.config.ts similarity index 87% rename from integration/apps/astro/src/sprite/svg-sprite.config.ts rename to integration/apps/astro/src/app-icons/svg-sprite.config.ts index 7ae905f..5355e19 100644 --- a/integration/apps/astro/src/sprite/svg-sprite.config.ts +++ b/integration/apps/astro/src/app-icons/svg-sprite.config.ts @@ -1,6 +1,6 @@ export default { mode: 'astro@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, } diff --git a/integration/apps/astro/src/pages/index.astro b/integration/apps/astro/src/pages/index.astro index 3f6d296..2afc78a 100644 --- a/integration/apps/astro/src/pages/index.astro +++ b/integration/apps/astro/src/pages/index.astro @@ -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'

Astro

- +
@@ -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'), + ], }) @@ -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; diff --git a/integration/apps/next-pages-turbopack/src/sprite/.gitignore b/integration/apps/astro/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/next-pages-turbopack/src/sprite/.gitignore rename to integration/apps/astro/src/remote-app-icons/.gitignore diff --git a/integration/apps/nuxt-vite/src/sprite/index.d.ts b/integration/apps/astro/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/nuxt-vite/src/sprite/index.d.ts rename to integration/apps/astro/src/remote-app-icons/index.d.ts diff --git a/integration/apps/nuxt-vite/src/sprite/index.js b/integration/apps/astro/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/nuxt-vite/src/sprite/index.js rename to integration/apps/astro/src/remote-app-icons/index.js diff --git a/integration/apps/astro/src/remote-app-icons/svg-sprite.config.js b/integration/apps/astro/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..8be4544 --- /dev/null +++ b/integration/apps/astro/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/astro/src/type-probe.ts b/integration/apps/astro/src/type-probe.ts index fc24b32..4bd82d1 100644 --- a/integration/apps/astro/src/type-probe.ts +++ b/integration/apps/astro/src/type-probe.ts @@ -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 } diff --git a/integration/apps/lit-vite/package.json b/integration/apps/lit-vite/package.json index 870359f..36b44b1 100644 --- a/integration/apps/lit-vite/package.json +++ b/integration/apps/lit-vite/package.json @@ -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" diff --git a/integration/apps/next-pages-webpack/src/sprite/.gitignore b/integration/apps/lit-vite/src/app-icons/.gitignore similarity index 100% rename from integration/apps/next-pages-webpack/src/sprite/.gitignore rename to integration/apps/lit-vite/src/app-icons/.gitignore diff --git a/integration/apps/nuxt-webpack/src/sprite/index.d.ts b/integration/apps/lit-vite/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/nuxt-webpack/src/sprite/index.d.ts rename to integration/apps/lit-vite/src/app-icons/index.d.ts diff --git a/integration/apps/nuxt-webpack/src/sprite/index.js b/integration/apps/lit-vite/src/app-icons/index.js similarity index 100% rename from integration/apps/nuxt-webpack/src/sprite/index.js rename to integration/apps/lit-vite/src/app-icons/index.js diff --git a/integration/apps/lit-vite/src/sprite/svg-sprite.config.json b/integration/apps/lit-vite/src/app-icons/svg-sprite.config.json similarity index 84% rename from integration/apps/lit-vite/src/sprite/svg-sprite.config.json rename to integration/apps/lit-vite/src/app-icons/svg-sprite.config.json index 11325da..9303126 100644 --- a/integration/apps/lit-vite/src/sprite/svg-sprite.config.json +++ b/integration/apps/lit-vite/src/app-icons/svg-sprite.config.json @@ -1,6 +1,6 @@ { "mode": "lit@vite", - "name": "icons", + "name": "app", "input": "../../../../fixtures/icons/check.svg", "generatedNotice": false } diff --git a/integration/apps/lit-vite/src/generated-contract.typecheck.ts b/integration/apps/lit-vite/src/generated-contract.typecheck.ts index 8204ef3..0046045 100644 --- a/integration/apps/lit-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/lit-vite/src/generated-contract.typecheck.ts @@ -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' diff --git a/integration/apps/lit-vite/src/main.js b/integration/apps/lit-vite/src/main.js index 8244b67..b17b12a 100644 --- a/integration/apps/lit-vite/src/main.js +++ b/integration/apps/lit-vite/src/main.js @@ -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 = `

Lit + Vite

- + > + ` -document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest] +document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest] diff --git a/integration/apps/nuxt-vite/src/sprite/.gitignore b/integration/apps/lit-vite/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/nuxt-vite/src/sprite/.gitignore rename to integration/apps/lit-vite/src/remote-app-icons/.gitignore diff --git a/integration/apps/preact-vite/src/sprite/index.d.ts b/integration/apps/lit-vite/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/preact-vite/src/sprite/index.d.ts rename to integration/apps/lit-vite/src/remote-app-icons/index.d.ts diff --git a/integration/apps/preact-vite/src/sprite/index.js b/integration/apps/lit-vite/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/preact-vite/src/sprite/index.js rename to integration/apps/lit-vite/src/remote-app-icons/index.js diff --git a/integration/apps/lit-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/lit-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..b4924fa --- /dev/null +++ b/integration/apps/lit-vite/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/lit-webpack/package.json b/integration/apps/lit-webpack/package.json index 81f5714..5f84287 100644 --- a/integration/apps/lit-webpack/package.json +++ b/integration/apps/lit-webpack/package.json @@ -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" diff --git a/integration/apps/nuxt-webpack/src/sprite/.gitignore b/integration/apps/lit-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/nuxt-webpack/src/sprite/.gitignore rename to integration/apps/lit-webpack/src/app-icons/.gitignore diff --git a/integration/apps/preact-webpack/src/sprite/index.d.ts b/integration/apps/lit-webpack/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/preact-webpack/src/sprite/index.d.ts rename to integration/apps/lit-webpack/src/app-icons/index.d.ts diff --git a/integration/apps/preact-webpack/src/sprite/index.js b/integration/apps/lit-webpack/src/app-icons/index.js similarity index 100% rename from integration/apps/preact-webpack/src/sprite/index.js rename to integration/apps/lit-webpack/src/app-icons/index.js diff --git a/integration/apps/lit-webpack/src/sprite/svg-sprite.config.json b/integration/apps/lit-webpack/src/app-icons/svg-sprite.config.json similarity index 84% rename from integration/apps/lit-webpack/src/sprite/svg-sprite.config.json rename to integration/apps/lit-webpack/src/app-icons/svg-sprite.config.json index 0361df5..69e17b5 100644 --- a/integration/apps/lit-webpack/src/sprite/svg-sprite.config.json +++ b/integration/apps/lit-webpack/src/app-icons/svg-sprite.config.json @@ -1,6 +1,6 @@ { "mode": "lit@webpack", - "name": "icons", + "name": "app", "input": "../../../../fixtures/icons/check.svg", "generatedNotice": false } diff --git a/integration/apps/lit-webpack/src/generated-contract.typecheck.ts b/integration/apps/lit-webpack/src/generated-contract.typecheck.ts index 8204ef3..0046045 100644 --- a/integration/apps/lit-webpack/src/generated-contract.typecheck.ts +++ b/integration/apps/lit-webpack/src/generated-contract.typecheck.ts @@ -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' diff --git a/integration/apps/lit-webpack/src/main.js b/integration/apps/lit-webpack/src/main.js index 85c6187..52c122f 100644 --- a/integration/apps/lit-webpack/src/main.js +++ b/integration/apps/lit-webpack/src/main.js @@ -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 = `

Lit + Webpack

- + > + ` -document.querySelector('gromlab-sprite-viewer').sources = [spriteManifest] +document.querySelector('gromlab-sprite-viewer').sources = [appManifest, remoteAppManifest] diff --git a/integration/apps/preact-vite/src/sprite/.gitignore b/integration/apps/lit-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/preact-vite/src/sprite/.gitignore rename to integration/apps/lit-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/qwik-vite/src/sprite/index.d.ts b/integration/apps/lit-webpack/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/qwik-vite/src/sprite/index.d.ts rename to integration/apps/lit-webpack/src/remote-app-icons/index.d.ts diff --git a/integration/apps/solid-webpack/src/sprite/index.js b/integration/apps/lit-webpack/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/solid-webpack/src/sprite/index.js rename to integration/apps/lit-webpack/src/remote-app-icons/index.js diff --git a/integration/apps/lit-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/lit-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..2d65bc2 --- /dev/null +++ b/integration/apps/lit-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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, +} diff --git a/integration/apps/next-app-turbopack/app/page.tsx b/integration/apps/next-app-turbopack/app/page.tsx index e43bd8a..016b6ab 100644 --- a/integration/apps/next-app-turbopack/app/page.tsx +++ b/integration/apps/next-app-turbopack/app/page.tsx @@ -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 (

Next.js App Router + Turbopack

- +
) diff --git a/integration/apps/next-app-turbopack/app/sprite-viewer.tsx b/integration/apps/next-app-turbopack/app/sprite-viewer.tsx index 550501c..72ffd63 100644 --- a/integration/apps/next-app-turbopack/app/sprite-viewer.tsx +++ b/integration/apps/next-app-turbopack/app/sprite-viewer.tsx @@ -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() { diff --git a/integration/apps/next-app-turbopack/generated-contract.typecheck.tsx b/integration/apps/next-app-turbopack/generated-contract.typecheck.tsx index 1b8ac4e..a60303b 100644 --- a/integration/apps/next-app-turbopack/generated-contract.typecheck.tsx +++ b/integration/apps/next-app-turbopack/generated-contract.typecheck.tsx @@ -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 -void +void allAppIconNames +void +void +void +void // @ts-expect-error Unknown icon names must be rejected by generated declarations. -void +void diff --git a/integration/apps/next-app-turbopack/package.json b/integration/apps/next-app-turbopack/package.json index 7988150..90cfe28 100644 --- a/integration/apps/next-app-turbopack/package.json +++ b/integration/apps/next-app-turbopack/package.json @@ -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", diff --git a/integration/apps/preact-webpack/src/sprite/.gitignore b/integration/apps/next-app-turbopack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/preact-webpack/src/sprite/.gitignore rename to integration/apps/next-app-turbopack/src/app-icons/.gitignore diff --git a/integration/apps/next-app-turbopack/src/sprite/index.ts b/integration/apps/next-app-turbopack/src/app-icons/index.ts similarity index 100% rename from integration/apps/next-app-turbopack/src/sprite/index.ts rename to integration/apps/next-app-turbopack/src/app-icons/index.ts diff --git a/integration/apps/next-app-turbopack/src/sprite/svg-sprite.config.ts b/integration/apps/next-app-turbopack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/next-app-turbopack/src/sprite/svg-sprite.config.ts rename to integration/apps/next-app-turbopack/src/app-icons/svg-sprite.config.ts index bbcc2c5..4152dea 100644 --- a/integration/apps/next-app-turbopack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/next-app-turbopack/src/app-icons/svg-sprite.config.ts @@ -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, }) diff --git a/integration/apps/qwik-vite/src/sprite/.gitignore b/integration/apps/next-app-turbopack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/qwik-vite/src/sprite/.gitignore rename to integration/apps/next-app-turbopack/src/remote-app-icons/.gitignore diff --git a/integration/apps/next-app-webpack/src/sprite/index.ts b/integration/apps/next-app-turbopack/src/remote-app-icons/index.ts similarity index 100% rename from integration/apps/next-app-webpack/src/sprite/index.ts rename to integration/apps/next-app-turbopack/src/remote-app-icons/index.ts diff --git a/integration/apps/next-app-turbopack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/next-app-turbopack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..9e96d8f --- /dev/null +++ b/integration/apps/next-app-turbopack/src/remote-app-icons/svg-sprite.config.js @@ -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', +} diff --git a/integration/apps/next-app-webpack/app/page.tsx b/integration/apps/next-app-webpack/app/page.tsx index ff2ff3e..422f2de 100644 --- a/integration/apps/next-app-webpack/app/page.tsx +++ b/integration/apps/next-app-webpack/app/page.tsx @@ -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 (

Next.js App Router + Webpack

- +
) diff --git a/integration/apps/next-app-webpack/app/sprite-viewer.tsx b/integration/apps/next-app-webpack/app/sprite-viewer.tsx index b77ec20..296dd31 100644 --- a/integration/apps/next-app-webpack/app/sprite-viewer.tsx +++ b/integration/apps/next-app-webpack/app/sprite-viewer.tsx @@ -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() { diff --git a/integration/apps/next-app-webpack/package.json b/integration/apps/next-app-webpack/package.json index 746de2f..3be7240 100644 --- a/integration/apps/next-app-webpack/package.json +++ b/integration/apps/next-app-webpack/package.json @@ -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", diff --git a/integration/apps/react-vite/src/sprite/.gitignore b/integration/apps/next-app-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/react-vite/src/sprite/.gitignore rename to integration/apps/next-app-webpack/src/app-icons/.gitignore diff --git a/integration/apps/next-pages-turbopack/src/sprite/index.ts b/integration/apps/next-app-webpack/src/app-icons/index.ts similarity index 100% rename from integration/apps/next-pages-turbopack/src/sprite/index.ts rename to integration/apps/next-app-webpack/src/app-icons/index.ts diff --git a/integration/apps/next-app-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/next-app-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/next-app-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/next-app-webpack/src/app-icons/svg-sprite.config.ts index 8baf3fd..d9b237e 100644 --- a/integration/apps/next-app-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/next-app-webpack/src/app-icons/svg-sprite.config.ts @@ -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, }) diff --git a/integration/apps/react-webpack/src/sprite/.gitignore b/integration/apps/next-app-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/react-webpack/src/sprite/.gitignore rename to integration/apps/next-app-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/next-pages-webpack/src/sprite/index.ts b/integration/apps/next-app-webpack/src/remote-app-icons/index.ts similarity index 100% rename from integration/apps/next-pages-webpack/src/sprite/index.ts rename to integration/apps/next-app-webpack/src/remote-app-icons/index.ts diff --git a/integration/apps/next-app-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/next-app-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..6d32296 --- /dev/null +++ b/integration/apps/next-app-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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', +} diff --git a/integration/apps/next-pages-turbopack/package.json b/integration/apps/next-pages-turbopack/package.json index 00c7b3f..2fd0a38 100644 --- a/integration/apps/next-pages-turbopack/package.json +++ b/integration/apps/next-pages-turbopack/package.json @@ -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", diff --git a/integration/apps/next-pages-turbopack/pages/index.tsx b/integration/apps/next-pages-turbopack/pages/index.tsx index 31f8d54..f792ac8 100644 --- a/integration/apps/next-pages-turbopack/pages/index.tsx +++ b/integration/apps/next-pages-turbopack/pages/index.tsx @@ -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 (

Next.js Pages Router + Turbopack

- +
) diff --git a/integration/apps/solid-start-vite/src/sprite/.gitignore b/integration/apps/next-pages-turbopack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/solid-start-vite/src/sprite/.gitignore rename to integration/apps/next-pages-turbopack/src/app-icons/.gitignore diff --git a/integration/apps/react-vite/src/sprite/index.ts b/integration/apps/next-pages-turbopack/src/app-icons/index.ts similarity index 100% rename from integration/apps/react-vite/src/sprite/index.ts rename to integration/apps/next-pages-turbopack/src/app-icons/index.ts diff --git a/integration/apps/next-pages-turbopack/src/sprite/svg-sprite.config.ts b/integration/apps/next-pages-turbopack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/next-pages-turbopack/src/sprite/svg-sprite.config.ts rename to integration/apps/next-pages-turbopack/src/app-icons/svg-sprite.config.ts index 30b8867..29c9270 100644 --- a/integration/apps/next-pages-turbopack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/next-pages-turbopack/src/app-icons/svg-sprite.config.ts @@ -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, }) diff --git a/integration/apps/solid-vite/src/sprite/.gitignore b/integration/apps/next-pages-turbopack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/solid-vite/src/sprite/.gitignore rename to integration/apps/next-pages-turbopack/src/remote-app-icons/.gitignore diff --git a/integration/apps/react-webpack/src/sprite/index.ts b/integration/apps/next-pages-turbopack/src/remote-app-icons/index.ts similarity index 100% rename from integration/apps/react-webpack/src/sprite/index.ts rename to integration/apps/next-pages-turbopack/src/remote-app-icons/index.ts diff --git a/integration/apps/next-pages-turbopack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/next-pages-turbopack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..98f616d --- /dev/null +++ b/integration/apps/next-pages-turbopack/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'next@pages/turbopack', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/next-pages-webpack/package.json b/integration/apps/next-pages-webpack/package.json index 0055a29..bf92801 100644 --- a/integration/apps/next-pages-webpack/package.json +++ b/integration/apps/next-pages-webpack/package.json @@ -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", diff --git a/integration/apps/next-pages-webpack/pages/index.tsx b/integration/apps/next-pages-webpack/pages/index.tsx index 5f21dfa..6597bd0 100644 --- a/integration/apps/next-pages-webpack/pages/index.tsx +++ b/integration/apps/next-pages-webpack/pages/index.tsx @@ -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 (

Next.js Pages Router + Webpack

- +
) diff --git a/integration/apps/solid-webpack/src/sprite/.gitignore b/integration/apps/next-pages-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/solid-webpack/src/sprite/.gitignore rename to integration/apps/next-pages-webpack/src/app-icons/.gitignore diff --git a/integration/apps/qwik-vite/src/sprite/index.js b/integration/apps/next-pages-webpack/src/app-icons/index.ts similarity index 100% rename from integration/apps/qwik-vite/src/sprite/index.js rename to integration/apps/next-pages-webpack/src/app-icons/index.ts diff --git a/integration/apps/next-pages-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/next-pages-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/next-pages-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/next-pages-webpack/src/app-icons/svg-sprite.config.ts index c9eb5b8..6e34ac4 100644 --- a/integration/apps/next-pages-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/next-pages-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'next@pages/webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/standalone-vite/src/sprite/.gitignore b/integration/apps/next-pages-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/standalone-vite/src/sprite/.gitignore rename to integration/apps/next-pages-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/solid-start-vite/src/sprite/index.js b/integration/apps/next-pages-webpack/src/remote-app-icons/index.ts similarity index 100% rename from integration/apps/solid-start-vite/src/sprite/index.js rename to integration/apps/next-pages-webpack/src/remote-app-icons/index.ts diff --git a/integration/apps/next-pages-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/next-pages-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..1305e23 --- /dev/null +++ b/integration/apps/next-pages-webpack/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'next@pages/webpack', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/nuxt-vite/app/app.vue b/integration/apps/nuxt-vite/app/app.vue index 363da4a..7a42f2f 100644 --- a/integration/apps/nuxt-vite/app/app.vue +++ b/integration/apps/nuxt-vite/app/app.vue @@ -1,11 +1,12 @@ diff --git a/integration/apps/nuxt-vite/app/components/SpriteViewer.client.vue b/integration/apps/nuxt-vite/app/components/SpriteViewer.client.vue index dccc494..45cd9f2 100644 --- a/integration/apps/nuxt-vite/app/components/SpriteViewer.client.vue +++ b/integration/apps/nuxt-vite/app/components/SpriteViewer.client.vue @@ -4,7 +4,8 @@ import { defineSpriteViewerElement } from '@gromlab/svg-sprites/viewer' defineSpriteViewerElement() 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'), ] diff --git a/integration/apps/nuxt-vite/app/generated-contract.typecheck.ts b/integration/apps/nuxt-vite/app/generated-contract.typecheck.ts index 08d2de8..6f23b4b 100644 --- a/integration/apps/nuxt-vite/app/generated-contract.typecheck.ts +++ b/integration/apps/nuxt-vite/app/generated-contract.typecheck.ts @@ -1,15 +1,30 @@ -import { IconsIcon } from '../src/sprite/.svg-sprite/index.js' -import type { IconsIconName, IconsIconProps } from '../src/sprite/.svg-sprite/index.js' +import { AppIcon } from '../src/app-icons/.svg-sprite/index.js' +import type { AppIconName, AppIconProps } from '../src/app-icons/.svg-sprite/index.js' +import { RemoteAppIcon } from '../src/remote-app-icons/.svg-sprite/index.js' +import type { + RemoteAppIconName, + RemoteAppIconProps, +} from '../src/remote-app-icons/.svg-sprite/index.js' -const iconName: IconsIconName = 'check' -const iconProps: IconsIconProps = { +const iconName: AppIconName = 'check' +const iconProps: AppIconProps = { icon: iconName, width: 64, style: { '--icon-color-1': '#16a34a' }, } +const remoteIconName: RemoteAppIconName = 'check' +const remoteIconProps: RemoteAppIconProps = { + icon: remoteIconName, + width: 64, + style: { '--icon-color-1': '#16a34a' }, +} -void [IconsIcon, iconProps] +void [AppIcon, RemoteAppIcon, iconProps, remoteIconProps] // @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 diff --git a/integration/apps/nuxt-vite/package.json b/integration/apps/nuxt-vite/package.json index 5b77384..8bfe75f 100644 --- a/integration/apps/nuxt-vite/package.json +++ b/integration/apps/nuxt-vite/package.json @@ -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": "nuxt typecheck", "build": "npm run sprites && nuxt build", "dev": "npm run sprites && nuxt dev", diff --git a/integration/apps/standalone-webpack/src/sprite/.gitignore b/integration/apps/nuxt-vite/src/app-icons/.gitignore similarity index 100% rename from integration/apps/standalone-webpack/src/sprite/.gitignore rename to integration/apps/nuxt-vite/src/app-icons/.gitignore diff --git a/integration/apps/solid-start-vite/src/sprite/index.d.ts b/integration/apps/nuxt-vite/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/solid-start-vite/src/sprite/index.d.ts rename to integration/apps/nuxt-vite/src/app-icons/index.d.ts diff --git a/integration/apps/svelte-vite/src/sprite/index.js b/integration/apps/nuxt-vite/src/app-icons/index.js similarity index 100% rename from integration/apps/svelte-vite/src/sprite/index.js rename to integration/apps/nuxt-vite/src/app-icons/index.js diff --git a/integration/apps/nuxt-vite/src/sprite/svg-sprite.config.ts b/integration/apps/nuxt-vite/src/app-icons/svg-sprite.config.ts similarity index 91% rename from integration/apps/nuxt-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/nuxt-vite/src/app-icons/svg-sprite.config.ts index c28161d..b318eeb 100644 --- a/integration/apps/nuxt-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/nuxt-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'nuxt@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/svelte-vite/src/sprite/.gitignore b/integration/apps/nuxt-vite/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/svelte-vite/src/sprite/.gitignore rename to integration/apps/nuxt-vite/src/remote-app-icons/.gitignore diff --git a/integration/apps/solid-vite/src/sprite/index.d.ts b/integration/apps/nuxt-vite/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/solid-vite/src/sprite/index.d.ts rename to integration/apps/nuxt-vite/src/remote-app-icons/index.d.ts diff --git a/integration/apps/svelte-webpack/src/sprite/index.js b/integration/apps/nuxt-vite/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/svelte-webpack/src/sprite/index.js rename to integration/apps/nuxt-vite/src/remote-app-icons/index.js diff --git a/integration/apps/nuxt-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/nuxt-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..224ddd7 --- /dev/null +++ b/integration/apps/nuxt-vite/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'nuxt@vite', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/nuxt-webpack/app/app.vue b/integration/apps/nuxt-webpack/app/app.vue index b17d060..b261892 100644 --- a/integration/apps/nuxt-webpack/app/app.vue +++ b/integration/apps/nuxt-webpack/app/app.vue @@ -1,11 +1,12 @@ diff --git a/integration/apps/nuxt-webpack/app/components/SpriteViewer.client.vue b/integration/apps/nuxt-webpack/app/components/SpriteViewer.client.vue index b8ec9b6..72ee560 100644 --- a/integration/apps/nuxt-webpack/app/components/SpriteViewer.client.vue +++ b/integration/apps/nuxt-webpack/app/components/SpriteViewer.client.vue @@ -4,7 +4,8 @@ import { defineSpriteViewerElement } from '@gromlab/svg-sprites/viewer' defineSpriteViewerElement() 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'), ] diff --git a/integration/apps/nuxt-webpack/app/generated-contract.typecheck.ts b/integration/apps/nuxt-webpack/app/generated-contract.typecheck.ts index 08d2de8..6f23b4b 100644 --- a/integration/apps/nuxt-webpack/app/generated-contract.typecheck.ts +++ b/integration/apps/nuxt-webpack/app/generated-contract.typecheck.ts @@ -1,15 +1,30 @@ -import { IconsIcon } from '../src/sprite/.svg-sprite/index.js' -import type { IconsIconName, IconsIconProps } from '../src/sprite/.svg-sprite/index.js' +import { AppIcon } from '../src/app-icons/.svg-sprite/index.js' +import type { AppIconName, AppIconProps } from '../src/app-icons/.svg-sprite/index.js' +import { RemoteAppIcon } from '../src/remote-app-icons/.svg-sprite/index.js' +import type { + RemoteAppIconName, + RemoteAppIconProps, +} from '../src/remote-app-icons/.svg-sprite/index.js' -const iconName: IconsIconName = 'check' -const iconProps: IconsIconProps = { +const iconName: AppIconName = 'check' +const iconProps: AppIconProps = { icon: iconName, width: 64, style: { '--icon-color-1': '#16a34a' }, } +const remoteIconName: RemoteAppIconName = 'check' +const remoteIconProps: RemoteAppIconProps = { + icon: remoteIconName, + width: 64, + style: { '--icon-color-1': '#16a34a' }, +} -void [IconsIcon, iconProps] +void [AppIcon, RemoteAppIcon, iconProps, remoteIconProps] // @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 diff --git a/integration/apps/nuxt-webpack/package.json b/integration/apps/nuxt-webpack/package.json index 7a74b54..76ac0a8 100644 --- a/integration/apps/nuxt-webpack/package.json +++ b/integration/apps/nuxt-webpack/package.json @@ -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": "nuxt typecheck", "build": "npm run sprites && nuxt build", "dev": "npm run sprites && nuxt dev", diff --git a/integration/apps/svelte-webpack/src/sprite/.gitignore b/integration/apps/nuxt-webpack/src/app-icons/.gitignore similarity index 100% rename from integration/apps/svelte-webpack/src/sprite/.gitignore rename to integration/apps/nuxt-webpack/src/app-icons/.gitignore diff --git a/integration/apps/solid-webpack/src/sprite/index.d.ts b/integration/apps/nuxt-webpack/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/solid-webpack/src/sprite/index.d.ts rename to integration/apps/nuxt-webpack/src/app-icons/index.d.ts diff --git a/integration/apps/sveltekit/src/sprite/index.js b/integration/apps/nuxt-webpack/src/app-icons/index.js similarity index 100% rename from integration/apps/sveltekit/src/sprite/index.js rename to integration/apps/nuxt-webpack/src/app-icons/index.js diff --git a/integration/apps/nuxt-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/nuxt-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/nuxt-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/nuxt-webpack/src/app-icons/svg-sprite.config.ts index 50f16be..c871fab 100644 --- a/integration/apps/nuxt-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/nuxt-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'nuxt@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/sveltekit/src/sprite/.gitignore b/integration/apps/nuxt-webpack/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/sveltekit/src/sprite/.gitignore rename to integration/apps/nuxt-webpack/src/remote-app-icons/.gitignore diff --git a/integration/apps/svelte-vite/src/sprite/index.d.ts b/integration/apps/nuxt-webpack/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/svelte-vite/src/sprite/index.d.ts rename to integration/apps/nuxt-webpack/src/remote-app-icons/index.d.ts diff --git a/integration/apps/vue-webpack/src/sprite/index.js b/integration/apps/nuxt-webpack/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/vue-webpack/src/sprite/index.js rename to integration/apps/nuxt-webpack/src/remote-app-icons/index.js diff --git a/integration/apps/nuxt-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/nuxt-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..1e0c16d --- /dev/null +++ b/integration/apps/nuxt-webpack/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'nuxt@webpack', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/preact-vite/package.json b/integration/apps/preact-vite/package.json index 191e53a..98a56df 100644 --- a/integration/apps/preact-vite/package.json +++ b/integration/apps/preact-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && npm run typecheck && vite build", "dev": "npm run sprites && vite" diff --git a/integration/apps/vue-vite/src/sprite/.gitignore b/integration/apps/preact-vite/src/app-icons/.gitignore similarity index 100% rename from integration/apps/vue-vite/src/sprite/.gitignore rename to integration/apps/preact-vite/src/app-icons/.gitignore diff --git a/integration/apps/svelte-webpack/src/sprite/index.d.ts b/integration/apps/preact-vite/src/app-icons/index.d.ts similarity index 100% rename from integration/apps/svelte-webpack/src/sprite/index.d.ts rename to integration/apps/preact-vite/src/app-icons/index.d.ts diff --git a/integration/apps/sveltekit/src/sprite/index.d.ts b/integration/apps/preact-vite/src/app-icons/index.js similarity index 100% rename from integration/apps/sveltekit/src/sprite/index.d.ts rename to integration/apps/preact-vite/src/app-icons/index.js diff --git a/integration/apps/preact-vite/src/sprite/svg-sprite.config.ts b/integration/apps/preact-vite/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/preact-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/preact-vite/src/app-icons/svg-sprite.config.ts index e449761..dc575f5 100644 --- a/integration/apps/preact-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/preact-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'preact@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/preact-vite/src/generated-contract.typecheck.ts b/integration/apps/preact-vite/src/generated-contract.typecheck.ts index 5b59d88..12f8e1c 100644 --- a/integration/apps/preact-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/preact-vite/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite/index.js' -import type { IconsIconName, IconsIconProps } from './sprite/index.js' +import { AppIcon, appIconNames } from './app-icons/index.js' +import type { AppIconName, AppIconProps } from './app-icons/index.js' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons/index.js' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons/index.js' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const appIconName: AppIconName = 'check' +const appProps: AppIconProps = { icon: appIconName, width: 24 } +const remoteAppIconName: RemoteAppIconName = 'check' +const remoteAppProps: RemoteAppIconProps = { icon: remoteAppIconName, width: 24 } -void IconsIcon -void iconsIconNames -void props +void AppIcon +void appIconNames +void appProps +void RemoteAppIcon +void remoteAppIconNames +void remoteAppProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/preact-vite/src/main.js b/integration/apps/preact-vite/src/main.js index e7f70b7..c5b9446 100644 --- a/integration/apps/preact-vite/src/main.js +++ b/integration/apps/preact-vite/src/main.js @@ -1,11 +1,13 @@ import { h, render } from 'preact' import '@gromlab/svg-sprites/viewer/element' -import { IconsIcon } from './sprite/index.js' +import { AppIcon } from './app-icons/index.js' +import { RemoteAppIcon } from './remote-app-icons/index.js' import './style.css' const 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'), ] function App() { @@ -15,7 +17,7 @@ function App() { return h('main', null, h('h1', null, 'Preact + Vite'), - h(IconsIcon, { + h(AppIcon, { 'data-testid': 'icon', 'data-app': 'preact-vite', icon: 'check', @@ -24,6 +26,15 @@ function App() { height: 64, style: { '--icon-color-1': '#16a34a' }, }), + h(RemoteAppIcon, { + 'data-testid': 'remote-icon', + 'data-app': 'preact-vite-remote', + icon: 'check', + 'aria-label': 'Remote check icon', + width: 64, + height: 64, + style: { '--icon-color-1': '#16a34a' }, + }), h('gromlab-sprite-viewer', { ref: connectViewer, 'viewer-title': 'Preact Vite Viewer', diff --git a/integration/apps/vue-webpack/src/sprite/.gitignore b/integration/apps/preact-vite/src/remote-app-icons/.gitignore similarity index 100% rename from integration/apps/vue-webpack/src/sprite/.gitignore rename to integration/apps/preact-vite/src/remote-app-icons/.gitignore diff --git a/integration/apps/vue-vite/src/sprite/index.d.ts b/integration/apps/preact-vite/src/remote-app-icons/index.d.ts similarity index 100% rename from integration/apps/vue-vite/src/sprite/index.d.ts rename to integration/apps/preact-vite/src/remote-app-icons/index.d.ts diff --git a/integration/apps/vue-webpack/src/sprite/index.d.ts b/integration/apps/preact-vite/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/vue-webpack/src/sprite/index.d.ts rename to integration/apps/preact-vite/src/remote-app-icons/index.js diff --git a/integration/apps/preact-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/preact-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..427b454 --- /dev/null +++ b/integration/apps/preact-vite/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'preact@vite', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/preact-webpack/package.json b/integration/apps/preact-webpack/package.json index 7ba31a7..0e40761 100644 --- a/integration/apps/preact-webpack/package.json +++ b/integration/apps/preact-webpack/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && npm run typecheck && webpack --mode production", "dev": "npm run sprites && webpack serve --mode development" diff --git a/integration/apps/preact-webpack/src/app-icons/.gitignore b/integration/apps/preact-webpack/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/preact-webpack/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/preact-webpack/src/app-icons/index.d.ts b/integration/apps/preact-webpack/src/app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/preact-webpack/src/app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/preact-webpack/src/app-icons/index.js b/integration/apps/preact-webpack/src/app-icons/index.js new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/preact-webpack/src/app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/preact-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/preact-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/preact-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/preact-webpack/src/app-icons/svg-sprite.config.ts index ad5e507..bf478cd 100644 --- a/integration/apps/preact-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/preact-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'preact@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/preact-webpack/src/generated-contract.typecheck.ts b/integration/apps/preact-webpack/src/generated-contract.typecheck.ts index 5b59d88..12f8e1c 100644 --- a/integration/apps/preact-webpack/src/generated-contract.typecheck.ts +++ b/integration/apps/preact-webpack/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite/index.js' -import type { IconsIconName, IconsIconProps } from './sprite/index.js' +import { AppIcon, appIconNames } from './app-icons/index.js' +import type { AppIconName, AppIconProps } from './app-icons/index.js' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons/index.js' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons/index.js' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const appIconName: AppIconName = 'check' +const appProps: AppIconProps = { icon: appIconName, width: 24 } +const remoteAppIconName: RemoteAppIconName = 'check' +const remoteAppProps: RemoteAppIconProps = { icon: remoteAppIconName, width: 24 } -void IconsIcon -void iconsIconNames -void props +void AppIcon +void appIconNames +void appProps +void RemoteAppIcon +void remoteAppIconNames +void remoteAppProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/preact-webpack/src/main.js b/integration/apps/preact-webpack/src/main.js index 58b4de4..db6c4d4 100644 --- a/integration/apps/preact-webpack/src/main.js +++ b/integration/apps/preact-webpack/src/main.js @@ -1,11 +1,13 @@ import { h, render } from 'preact' import '@gromlab/svg-sprites/viewer/element' -import { IconsIcon } from './sprite/index.js' +import { AppIcon } from './app-icons/index.js' +import { RemoteAppIcon } from './remote-app-icons/index.js' import './style.css' const 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'), ] function App() { @@ -15,7 +17,7 @@ function App() { return h('main', null, h('h1', null, 'Preact + Webpack'), - h(IconsIcon, { + h(AppIcon, { 'data-testid': 'icon', 'data-app': 'preact-webpack', icon: 'check', @@ -24,6 +26,15 @@ function App() { height: 64, style: { '--icon-color-1': '#16a34a' }, }), + h(RemoteAppIcon, { + 'data-testid': 'remote-icon', + 'data-app': 'preact-webpack-remote', + icon: 'check', + 'aria-label': 'Remote check icon', + width: 64, + height: 64, + style: { '--icon-color-1': '#16a34a' }, + }), h('gromlab-sprite-viewer', { ref: connectViewer, 'viewer-title': 'Preact Webpack Viewer', diff --git a/integration/apps/preact-webpack/src/remote-app-icons/.gitignore b/integration/apps/preact-webpack/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/preact-webpack/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/preact-webpack/src/remote-app-icons/index.d.ts b/integration/apps/preact-webpack/src/remote-app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/preact-webpack/src/remote-app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/preact-webpack/src/remote-app-icons/index.js b/integration/apps/preact-webpack/src/remote-app-icons/index.js new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/preact-webpack/src/remote-app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/preact-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/preact-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..7e840f8 --- /dev/null +++ b/integration/apps/preact-webpack/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'preact@webpack', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/qwik-vite/package.json b/integration/apps/qwik-vite/package.json index cbdc8ef..e6a526e 100644 --- a/integration/apps/qwik-vite/package.json +++ b/integration/apps/qwik-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && npm run typecheck && vite build", "dev": "npm run sprites && vite --mode ssr" diff --git a/integration/apps/qwik-vite/src/app-icons/.gitignore b/integration/apps/qwik-vite/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/qwik-vite/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/qwik-vite/src/app-icons/index.d.ts b/integration/apps/qwik-vite/src/app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/qwik-vite/src/app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-vite/src/sprite/index.js b/integration/apps/qwik-vite/src/app-icons/index.js similarity index 100% rename from integration/apps/solid-vite/src/sprite/index.js rename to integration/apps/qwik-vite/src/app-icons/index.js diff --git a/integration/apps/qwik-vite/src/sprite/svg-sprite.config.ts b/integration/apps/qwik-vite/src/app-icons/svg-sprite.config.ts similarity index 91% rename from integration/apps/qwik-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/qwik-vite/src/app-icons/svg-sprite.config.ts index 9650f0d..6a98a9c 100644 --- a/integration/apps/qwik-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/qwik-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'qwik@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/qwik-vite/src/generated-contract.typecheck.ts b/integration/apps/qwik-vite/src/generated-contract.typecheck.ts index 4c27e19..b9136c5 100644 --- a/integration/apps/qwik-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/qwik-vite/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite' -import type { IconsIconName, IconsIconProps } from './sprite' +import { AppIcon, appIconNames } from './app-icons' +import type { AppIconName, AppIconProps } from './app-icons' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const appIconName: AppIconName = 'check' +const appProps: AppIconProps = { icon: appIconName, width: 24 } +const remoteAppIconName: RemoteAppIconName = 'check' +const remoteAppProps: RemoteAppIconProps = { icon: remoteAppIconName, width: 24 } -void IconsIcon -void iconsIconNames -void props +void AppIcon +void appIconNames +void appProps +void RemoteAppIcon +void remoteAppIconNames +void remoteAppProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/qwik-vite/src/remote-app-icons/.gitignore b/integration/apps/qwik-vite/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/qwik-vite/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/qwik-vite/src/remote-app-icons/index.d.ts b/integration/apps/qwik-vite/src/remote-app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/qwik-vite/src/remote-app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/vue-vite/src/sprite/index.js b/integration/apps/qwik-vite/src/remote-app-icons/index.js similarity index 100% rename from integration/apps/vue-vite/src/sprite/index.js rename to integration/apps/qwik-vite/src/remote-app-icons/index.js diff --git a/integration/apps/qwik-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/qwik-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..c87d66c --- /dev/null +++ b/integration/apps/qwik-vite/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'qwik@vite', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/qwik-vite/src/root.jsx b/integration/apps/qwik-vite/src/root.jsx index 50ca18d..273fe5f 100644 --- a/integration/apps/qwik-vite/src/root.jsx +++ b/integration/apps/qwik-vite/src/root.jsx @@ -1,6 +1,7 @@ import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik' -import { IconsIcon } from './sprite' +import { AppIcon } from './app-icons' +import { RemoteAppIcon } from './remote-app-icons' import './style.css' export default component$(() => { @@ -10,14 +11,17 @@ export default component$(() => { await import('@gromlab/svg-sprites/viewer/element') const viewer = document.createElement('gromlab-sprite-viewer') viewer.viewerTitle = 'Qwik Vite Viewer' - viewer.sources = [() => import('./sprite/.svg-sprite/svg-sprite.manifest.js')] + viewer.sources = [ + () => import('./app-icons/.svg-sprite/svg-sprite.manifest.js'), + () => import('./remote-app-icons/.svg-sprite/svg-sprite.manifest.js'), + ] viewerHost.value?.append(viewer) }) return (

Qwik + Vite

- { height={64} style={{ '--icon-color-1': '#16a34a' }} /> +
) diff --git a/integration/apps/react-vite/package.json b/integration/apps/react-vite/package.json index ac3d717..98c57bc 100644 --- a/integration/apps/react-vite/package.json +++ b/integration/apps/react-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && tsc --noEmit && vite build", "dev": "npm run sprites && vite" diff --git a/integration/apps/react-vite/src/app-icons/.gitignore b/integration/apps/react-vite/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/react-vite/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/react-vite/src/app-icons/index.ts b/integration/apps/react-vite/src/app-icons/index.ts new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/react-vite/src/app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/react-vite/src/sprite/svg-sprite.config.ts b/integration/apps/react-vite/src/app-icons/svg-sprite.config.ts similarity index 91% rename from integration/apps/react-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/react-vite/src/app-icons/svg-sprite.config.ts index 8b5d43e..aac9434 100644 --- a/integration/apps/react-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/react-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'react@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/react-vite/src/main.tsx b/integration/apps/react-vite/src/main.tsx index 39d6489..612ebfe 100644 --- a/integration/apps/react-vite/src/main.tsx +++ b/integration/apps/react-vite/src/main.tsx @@ -2,18 +2,20 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { SpriteViewer } from '@gromlab/svg-sprites/react' -import { IconsIcon } from './sprite' +import { AppIcon } from './app-icons' +import { RemoteAppIcon } from './remote-app-icons' import './style.css' const 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'), ] as const createRoot(document.getElementById('root')!).render(

React + Vite

- +
, diff --git a/integration/apps/react-vite/src/remote-app-icons/.gitignore b/integration/apps/react-vite/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/react-vite/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/react-vite/src/remote-app-icons/index.ts b/integration/apps/react-vite/src/remote-app-icons/index.ts new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/react-vite/src/remote-app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/react-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/react-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..3dfff88 --- /dev/null +++ b/integration/apps/react-vite/src/remote-app-icons/svg-sprite.config.js @@ -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: 'react@vite', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/react-webpack/package.json b/integration/apps/react-webpack/package.json index dc85bd3..b7ab79a 100644 --- a/integration/apps/react-webpack/package.json +++ b/integration/apps/react-webpack/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && webpack --mode production", "dev": "npm run sprites && webpack serve --mode development" diff --git a/integration/apps/react-webpack/src/app-icons/.gitignore b/integration/apps/react-webpack/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/react-webpack/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/react-webpack/src/app-icons/index.ts b/integration/apps/react-webpack/src/app-icons/index.ts new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/react-webpack/src/app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/react-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/react-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/react-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/react-webpack/src/app-icons/svg-sprite.config.ts index 18e52eb..f69880f 100644 --- a/integration/apps/react-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/react-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'react@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/react-webpack/src/main.tsx b/integration/apps/react-webpack/src/main.tsx index 963fff8..6ef1d04 100644 --- a/integration/apps/react-webpack/src/main.tsx +++ b/integration/apps/react-webpack/src/main.tsx @@ -2,18 +2,20 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { SpriteViewer } from '@gromlab/svg-sprites/react' -import { IconsIcon } from './sprite' +import { AppIcon } from './app-icons' +import { RemoteAppIcon } from './remote-app-icons' import './style.css' const 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'), ] as const createRoot(document.getElementById('root')!).render(

React + Webpack

- +
, diff --git a/integration/apps/react-webpack/src/remote-app-icons/.gitignore b/integration/apps/react-webpack/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/react-webpack/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/react-webpack/src/remote-app-icons/index.ts b/integration/apps/react-webpack/src/remote-app-icons/index.ts new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/react-webpack/src/remote-app-icons/index.ts @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/react-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/react-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..499c735 --- /dev/null +++ b/integration/apps/react-webpack/src/remote-app-icons/svg-sprite.config.js @@ -0,0 +1,6 @@ +export default { + mode: 'react@webpack', + source: 'remote', + input: process.env.SVG_SPRITE_REMOTE_MANIFEST_URL + ?? '../../../standalone-server/cases/mixed-input/.svg-sprite/svg-sprite.manifest.json', +} diff --git a/integration/apps/solid-start-vite/package.json b/integration/apps/solid-start-vite/package.json index ab9e0ac..69b8481 100644 --- a/integration/apps/solid-start-vite/package.json +++ b/integration/apps/solid-start-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && npm run typecheck && vinxi build", "dev": "npm run sprites && vinxi dev" diff --git a/integration/apps/solid-start-vite/src/app-icons/.gitignore b/integration/apps/solid-start-vite/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-start-vite/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-start-vite/src/app-icons/index.d.ts b/integration/apps/solid-start-vite/src/app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-start-vite/src/app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-start-vite/src/app-icons/index.js b/integration/apps/solid-start-vite/src/app-icons/index.js new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/solid-start-vite/src/app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/solid-start-vite/src/sprite/svg-sprite.config.ts b/integration/apps/solid-start-vite/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/solid-start-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/solid-start-vite/src/app-icons/svg-sprite.config.ts index 07b8f27..b731199 100644 --- a/integration/apps/solid-start-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/solid-start-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'solid-start@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/solid-start-vite/src/generated-contract.typecheck.ts b/integration/apps/solid-start-vite/src/generated-contract.typecheck.ts index 4c27e19..e98e6fe 100644 --- a/integration/apps/solid-start-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/solid-start-vite/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite' -import type { IconsIconName, IconsIconProps } from './sprite' +import { AppIcon, appIconNames } from './app-icons' +import type { AppIconName, AppIconProps } from './app-icons' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const iconName: AppIconName = 'check' +const remoteIconName: RemoteAppIconName = 'check' +const props: AppIconProps = { icon: iconName, width: 24 } +const remoteProps: RemoteAppIconProps = { icon: remoteIconName, width: 24 } -void IconsIcon -void iconsIconNames +void AppIcon +void appIconNames +void RemoteAppIcon +void remoteAppIconNames void props +void remoteProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/solid-start-vite/src/remote-app-icons/.gitignore b/integration/apps/solid-start-vite/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-start-vite/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-start-vite/src/remote-app-icons/index.d.ts b/integration/apps/solid-start-vite/src/remote-app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-start-vite/src/remote-app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-start-vite/src/remote-app-icons/index.js b/integration/apps/solid-start-vite/src/remote-app-icons/index.js new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/solid-start-vite/src/remote-app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/solid-start-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/solid-start-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..c379d22 --- /dev/null +++ b/integration/apps/solid-start-vite/src/remote-app-icons/svg-sprite.config.js @@ -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: 'solid-start@vite', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/solid-start-vite/src/routes/index.jsx b/integration/apps/solid-start-vite/src/routes/index.jsx index d230979..46a4a34 100644 --- a/integration/apps/solid-start-vite/src/routes/index.jsx +++ b/integration/apps/solid-start-vite/src/routes/index.jsx @@ -1,6 +1,7 @@ import { onMount } from 'solid-js' -import { IconsIcon } from '../sprite' +import { AppIcon } from '../app-icons' +import { RemoteAppIcon } from '../remote-app-icons' export default function Home() { let viewerHost @@ -9,21 +10,33 @@ export default function Home() { await import('@gromlab/svg-sprites/viewer/element') const viewer = document.createElement('gromlab-sprite-viewer') viewer.viewerTitle = 'SolidStart Vite Viewer' - viewer.sources = [() => import('../sprite/.svg-sprite/svg-sprite.manifest.js')] + viewer.sources = [ + () => import('../app-icons/.svg-sprite/svg-sprite.manifest.js'), + () => import('../remote-app-icons/.svg-sprite/svg-sprite.manifest.js'), + ] viewerHost.append(viewer) }) return (

SolidStart + Vite

- +
diff --git a/integration/apps/solid-vite/package.json b/integration/apps/solid-vite/package.json index 30c845e..01be738 100644 --- a/integration/apps/solid-vite/package.json +++ b/integration/apps/solid-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && tsc --noEmit && vite build", "dev": "npm run sprites && vite" diff --git a/integration/apps/solid-vite/src/app-icons/.gitignore b/integration/apps/solid-vite/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-vite/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-vite/src/app-icons/index.d.ts b/integration/apps/solid-vite/src/app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-vite/src/app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-vite/src/app-icons/index.js b/integration/apps/solid-vite/src/app-icons/index.js new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/solid-vite/src/app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/solid-vite/src/sprite/svg-sprite.config.ts b/integration/apps/solid-vite/src/app-icons/svg-sprite.config.ts similarity index 91% rename from integration/apps/solid-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/solid-vite/src/app-icons/svg-sprite.config.ts index 608e50b..5a5441e 100644 --- a/integration/apps/solid-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/solid-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'solid@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/solid-vite/src/generated-contract.typecheck.ts b/integration/apps/solid-vite/src/generated-contract.typecheck.ts index 4c27e19..e98e6fe 100644 --- a/integration/apps/solid-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/solid-vite/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite' -import type { IconsIconName, IconsIconProps } from './sprite' +import { AppIcon, appIconNames } from './app-icons' +import type { AppIconName, AppIconProps } from './app-icons' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const iconName: AppIconName = 'check' +const remoteIconName: RemoteAppIconName = 'check' +const props: AppIconProps = { icon: iconName, width: 24 } +const remoteProps: RemoteAppIconProps = { icon: remoteIconName, width: 24 } -void IconsIcon -void iconsIconNames +void AppIcon +void appIconNames +void RemoteAppIcon +void remoteAppIconNames void props +void remoteProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/solid-vite/src/main.jsx b/integration/apps/solid-vite/src/main.jsx index dbe30a8..2c38a85 100644 --- a/integration/apps/solid-vite/src/main.jsx +++ b/integration/apps/solid-vite/src/main.jsx @@ -1,7 +1,8 @@ import { onMount } from 'solid-js' import { render } from 'solid-js/web' -import { IconsIcon } from './sprite' +import { AppIcon } from './app-icons' +import { RemoteAppIcon } from './remote-app-icons' import './style.css' function App() { @@ -11,21 +12,33 @@ function App() { await import('@gromlab/svg-sprites/viewer/element') const viewer = document.createElement('gromlab-sprite-viewer') viewer.viewerTitle = 'Solid Vite Viewer' - viewer.sources = [() => import('./sprite/.svg-sprite/svg-sprite.manifest.js')] + viewer.sources = [ + () => import('./app-icons/.svg-sprite/svg-sprite.manifest.js'), + () => import('./remote-app-icons/.svg-sprite/svg-sprite.manifest.js'), + ] viewerHost.append(viewer) }) return (

Solid + Vite

- +
diff --git a/integration/apps/solid-vite/src/remote-app-icons/.gitignore b/integration/apps/solid-vite/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-vite/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-vite/src/remote-app-icons/index.d.ts b/integration/apps/solid-vite/src/remote-app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-vite/src/remote-app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-vite/src/remote-app-icons/index.js b/integration/apps/solid-vite/src/remote-app-icons/index.js new file mode 100644 index 0000000..411538d --- /dev/null +++ b/integration/apps/solid-vite/src/remote-app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite' diff --git a/integration/apps/solid-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/solid-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..0f275a3 --- /dev/null +++ b/integration/apps/solid-vite/src/remote-app-icons/svg-sprite.config.js @@ -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: 'solid@vite', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/solid-vite/src/style.css b/integration/apps/solid-vite/src/style.css index 227e7fc..fcd6e82 100644 --- a/integration/apps/solid-vite/src/style.css +++ b/integration/apps/solid-vite/src/style.css @@ -9,7 +9,8 @@ body { padding: 40px; } -[data-testid='icon'] { +[data-testid='icon'], +[data-testid='remote-icon'] { width: 64px; height: 64px; } diff --git a/integration/apps/solid-webpack/package.json b/integration/apps/solid-webpack/package.json index b9e441d..c26bc9a 100644 --- a/integration/apps/solid-webpack/package.json +++ b/integration/apps/solid-webpack/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && npm run typecheck && webpack --mode production", "dev": "npm run sprites && webpack serve --mode development" diff --git a/integration/apps/solid-webpack/src/app-icons/.gitignore b/integration/apps/solid-webpack/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-webpack/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-webpack/src/app-icons/index.d.ts b/integration/apps/solid-webpack/src/app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-webpack/src/app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-webpack/src/app-icons/index.js b/integration/apps/solid-webpack/src/app-icons/index.js new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-webpack/src/app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/solid-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/solid-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/solid-webpack/src/app-icons/svg-sprite.config.ts index 994addb..180f7d2 100644 --- a/integration/apps/solid-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/solid-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'solid@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/solid-webpack/src/generated-contract.typecheck.ts b/integration/apps/solid-webpack/src/generated-contract.typecheck.ts index 5b59d88..0426001 100644 --- a/integration/apps/solid-webpack/src/generated-contract.typecheck.ts +++ b/integration/apps/solid-webpack/src/generated-contract.typecheck.ts @@ -1,13 +1,20 @@ -import { IconsIcon, iconsIconNames } from './sprite/index.js' -import type { IconsIconName, IconsIconProps } from './sprite/index.js' +import { AppIcon, appIconNames } from './app-icons/index.js' +import type { AppIconName, AppIconProps } from './app-icons/index.js' +import { RemoteAppIcon, remoteAppIconNames } from './remote-app-icons/index.js' +import type { RemoteAppIconName, RemoteAppIconProps } from './remote-app-icons/index.js' -const iconName: IconsIconName = 'check' -const props: IconsIconProps = { icon: iconName, width: 24 } +const iconName: AppIconName = 'check' +const remoteIconName: RemoteAppIconName = 'check' +const props: AppIconProps = { icon: iconName, width: 24 } +const remoteProps: RemoteAppIconProps = { icon: remoteIconName, width: 24 } -void IconsIcon -void iconsIconNames +void AppIcon +void appIconNames +void RemoteAppIcon +void remoteAppIconNames void props +void remoteProps // @ts-expect-error Generated icon names form a literal union. -const missingIcon: IconsIconName = 'missing' +const missingIcon: AppIconName = 'missing' void missingIcon diff --git a/integration/apps/solid-webpack/src/main.jsx b/integration/apps/solid-webpack/src/main.jsx index 325bebb..21e3f01 100644 --- a/integration/apps/solid-webpack/src/main.jsx +++ b/integration/apps/solid-webpack/src/main.jsx @@ -2,11 +2,13 @@ import { onMount } from 'solid-js' import { render } from 'solid-js/web' import '@gromlab/svg-sprites/viewer/element' -import { IconsIcon } from './sprite/index.js' +import { AppIcon } from './app-icons/index.js' +import { RemoteAppIcon } from './remote-app-icons/index.js' import './style.css' const 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'), ] function App() { @@ -19,14 +21,23 @@ function App() { return (

Solid + Webpack

- +
diff --git a/integration/apps/solid-webpack/src/remote-app-icons/.gitignore b/integration/apps/solid-webpack/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/solid-webpack/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/solid-webpack/src/remote-app-icons/index.d.ts b/integration/apps/solid-webpack/src/remote-app-icons/index.d.ts new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-webpack/src/remote-app-icons/index.d.ts @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-webpack/src/remote-app-icons/index.js b/integration/apps/solid-webpack/src/remote-app-icons/index.js new file mode 100644 index 0000000..ceeead8 --- /dev/null +++ b/integration/apps/solid-webpack/src/remote-app-icons/index.js @@ -0,0 +1 @@ +export * from './.svg-sprite/index.js' diff --git a/integration/apps/solid-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/solid-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..0c7ea8b --- /dev/null +++ b/integration/apps/solid-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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: 'solid@webpack', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/standalone-server/cases/http-only/svg-sprite.config.js b/integration/apps/standalone-server/cases/http-only/svg-sprite.config.js new file mode 100644 index 0000000..bf43161 --- /dev/null +++ b/integration/apps/standalone-server/cases/http-only/svg-sprite.config.js @@ -0,0 +1,17 @@ +const sourceOrigin = process.env.SVG_SPRITE_SOURCE_ORIGIN +const sourceSha256 = process.env.SVG_SPRITE_SOURCE_SHA256 + +if (!sourceOrigin || !sourceSha256) throw new Error('HTTP source origin and SHA-256 are required.') + +export default { + mode: 'standalone@server', + name: 'remote-http', + input: [ + { + name: 'folder open', + url: `${sourceOrigin}/sources/check.svg`, + sha256: sourceSha256, + }, + ], + generatedNotice: false, +} diff --git a/integration/apps/standalone-server/cases/mixed-input/svg-sprite.config.js b/integration/apps/standalone-server/cases/mixed-input/svg-sprite.config.js new file mode 100644 index 0000000..0b7cd12 --- /dev/null +++ b/integration/apps/standalone-server/cases/mixed-input/svg-sprite.config.js @@ -0,0 +1,13 @@ +const sourceOrigin = process.env.SVG_SPRITE_SOURCE_ORIGIN + +if (!sourceOrigin) throw new Error('SVG_SPRITE_SOURCE_ORIGIN is required.') + +export default { + mode: 'standalone@server', + name: 'remote-app', + input: [ + '../../../../fixtures/icons/duotone.svg', + { name: 'check', url: `${sourceOrigin}/sources/check.svg` }, + ], + generatedNotice: false, +} diff --git a/integration/apps/standalone-server/cases/transforms-disabled/svg-sprite.config.js b/integration/apps/standalone-server/cases/transforms-disabled/svg-sprite.config.js new file mode 100644 index 0000000..d51f196 --- /dev/null +++ b/integration/apps/standalone-server/cases/transforms-disabled/svg-sprite.config.js @@ -0,0 +1,11 @@ +export default { + mode: 'standalone@server', + name: 'remote-plain', + input: '../../../../fixtures/icons/duotone.svg', + transform: { + removeSize: false, + replaceColors: false, + addTransition: false, + }, + generatedNotice: false, +} diff --git a/integration/apps/standalone-server/package.json b/integration/apps/standalone-server/package.json new file mode 100644 index 0000000..8accfe1 --- /dev/null +++ b/integration/apps/standalone-server/package.json @@ -0,0 +1,15 @@ +{ + "name": "@svg-sprites-fixtures/standalone-server", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "sprites": "npm run sprites:mixed && npm run sprites:http && npm run sprites:plain && node verify-release.mjs", + "sprites:mixed": "svg-sprites cases/mixed-input/svg-sprite.config.js", + "sprites:http": "svg-sprites cases/http-only/svg-sprite.config.js", + "sprites:plain": "svg-sprites cases/transforms-disabled/svg-sprite.config.js" + }, + "devDependencies": { + "@gromlab/svg-sprites": "file:../../.." + } +} diff --git a/integration/apps/standalone-server/verify-release.mjs b/integration/apps/standalone-server/verify-release.mjs new file mode 100644 index 0000000..a7d8f2e --- /dev/null +++ b/integration/apps/standalone-server/verify-release.mjs @@ -0,0 +1,59 @@ +import assert from 'node:assert/strict' +import { createHash } from 'node:crypto' +import fs from 'node:fs' +import path from 'node:path' + +const casesRoot = path.join(import.meta.dirname, 'cases') + +function sha256(bytes) { + return createHash('sha256').update(bytes).digest('hex') +} + +function verifyCase(caseName, expected) { + const outputDir = path.join(casesRoot, caseName, '.svg-sprite') + const manifestPath = path.join(outputDir, 'svg-sprite.manifest.json') + const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) + + assert.equal(manifest.kind, '@gromlab/svg-sprites/server') + assert.equal(manifest.mode, 'standalone@server') + assert.equal(manifest.target, 'server') + assert.equal(manifest.name, expected.name) + assert.equal(manifest.iconCount, expected.icons.length) + assert.deepEqual(manifest.icons.map(({ name }) => name), expected.icons) + assert.deepEqual(manifest.transform, expected.transform) + + for (const profile of ['stack', 'stack-root-viewbox']) { + const asset = manifest.sprites[profile] + const filePath = path.resolve(outputDir, asset.href) + const bytes = fs.readFileSync(filePath) + assert.equal(bytes.byteLength, asset.byteLength) + assert.equal(sha256(bytes), asset.sha256) + assert.match(path.basename(filePath), new RegExp(`^sprite${profile === 'stack' ? '' : '-root-viewbox'}\\.[a-f0-9]{16}\\.svg$`)) + } + + assert.deepEqual(fs.readdirSync(outputDir).sort().length, 3) + assert.equal(fs.existsSync(path.join(outputDir, 'index.js')), false) + assert.equal(fs.existsSync(path.join(path.dirname(outputDir), '.gitignore')), false) + return manifest +} + +const defaults = { removeSize: true, replaceColors: true, addTransition: true } +verifyCase('mixed-input', { + name: 'remote-app', + icons: ['check', 'duotone'], + transform: defaults, +}) +const httpManifest = verifyCase('http-only', { + name: 'remote-http', + icons: ['folder open'], + transform: defaults, +}) +assert.match(httpManifest.icons[0].id, /^icon-[a-f0-9]{16}$/) +const plainManifest = verifyCase('transforms-disabled', { + name: 'remote-plain', + icons: ['duotone'], + transform: { removeSize: false, replaceColors: false, addTransition: false }, +}) +assert.equal(plainManifest.icons[0].colors.length, 0) + +console.log('Verified standalone@server integration cases.') diff --git a/integration/apps/standalone-vite/package.json b/integration/apps/standalone-vite/package.json index 6e8cf23..7ad2753 100644 --- a/integration/apps/standalone-vite/package.json +++ b/integration/apps/standalone-vite/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && tsc --noEmit && vite build", "dev": "npm run sprites && vite" diff --git a/integration/apps/standalone-vite/src/app-icons/.gitignore b/integration/apps/standalone-vite/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/standalone-vite/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/standalone-vite/src/app-icons/index.ts b/integration/apps/standalone-vite/src/app-icons/index.ts new file mode 100644 index 0000000..c1043e4 --- /dev/null +++ b/integration/apps/standalone-vite/src/app-icons/index.ts @@ -0,0 +1,9 @@ +export { + appIconIds, + appIconNames, + appIconTagName, + appSpriteUrl, + defineAppIconElement, + getAppIconHref, +} from './.svg-sprite/index.js' +export type { AppIconElement, AppIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone-vite/src/sprite/svg-sprite.config.ts b/integration/apps/standalone-vite/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/standalone-vite/src/sprite/svg-sprite.config.ts rename to integration/apps/standalone-vite/src/app-icons/svg-sprite.config.ts index 4e2b016..c68d921 100644 --- a/integration/apps/standalone-vite/src/sprite/svg-sprite.config.ts +++ b/integration/apps/standalone-vite/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'standalone@vite', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/standalone-vite/src/generated-contract.typecheck.ts b/integration/apps/standalone-vite/src/generated-contract.typecheck.ts index 0a988fa..316ba00 100644 --- a/integration/apps/standalone-vite/src/generated-contract.typecheck.ts +++ b/integration/apps/standalone-vite/src/generated-contract.typecheck.ts @@ -1,9 +1,15 @@ -import type { IconsIconElement } from './sprite' +import type { AppIconElement } from './app-icons' +import type { RemoteAppIconElement } from './remote-app-icons' -const icon = document.createElement('icons-icon') -const typedIcon: IconsIconElement = icon +const appIcon = document.createElement('app-icon') +const typedAppIcon: AppIconElement = appIcon +const remoteAppIcon = document.createElement('remote-app-icon') +const typedRemoteAppIcon: RemoteAppIconElement = remoteAppIcon -typedIcon.icon = 'check' +typedAppIcon.icon = 'check' +typedRemoteAppIcon.icon = 'check' // @ts-expect-error Generated icon names form a literal union. -typedIcon.icon = 'missing' +typedAppIcon.icon = 'missing' +// @ts-expect-error Generated remote icon names form a literal union. +typedRemoteAppIcon.icon = 'missing' diff --git a/integration/apps/standalone-vite/src/main.ts b/integration/apps/standalone-vite/src/main.ts index 366ca2e..2a9bc53 100644 --- a/integration/apps/standalone-vite/src/main.ts +++ b/integration/apps/standalone-vite/src/main.ts @@ -1,28 +1,43 @@ import '@gromlab/svg-sprites/viewer/element' import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer' -import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js' -import { defineIconsIconElement, iconsSpriteUrl } from './sprite' +import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js' +import { appSpriteUrl, defineAppIconElement } from './app-icons' +import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js' +import { defineRemoteAppIconElement, remoteAppSpriteUrl } from './remote-app-icons' import './style.css' -const check = spriteManifest.icons.find((icon) => icon.name === 'check') -if (!check || spriteManifest.spriteUrl !== iconsSpriteUrl) { +const appCheck = appManifest.icons.find((icon) => icon.name === 'check') +if (!appCheck || appManifest.spriteUrl !== appSpriteUrl) { throw new Error('Generated Vite facade and manifest disagree.') } -defineIconsIconElement() +const remoteAppCheck = remoteAppManifest.icons.find((icon) => icon.name === 'check') +if (!remoteAppCheck || remoteAppManifest.spriteUrl !== remoteAppSpriteUrl) { + throw new Error('Generated remote Vite facade and manifest disagree.') +} + +defineAppIconElement() +defineRemoteAppIconElement() document.querySelector('#app')!.innerHTML = `

Standalone + Vite

- + > + ` const viewer = document.querySelector('gromlab-sprite-viewer')! viewer.viewerTitle = 'Standalone Vite Viewer' -viewer.sources = [spriteManifest] +viewer.sources = [appManifest, remoteAppManifest] diff --git a/integration/apps/standalone-vite/src/remote-app-icons/.gitignore b/integration/apps/standalone-vite/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/standalone-vite/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/standalone-vite/src/remote-app-icons/index.ts b/integration/apps/standalone-vite/src/remote-app-icons/index.ts new file mode 100644 index 0000000..cc4b9d9 --- /dev/null +++ b/integration/apps/standalone-vite/src/remote-app-icons/index.ts @@ -0,0 +1,9 @@ +export { + defineRemoteAppIconElement, + getRemoteAppIconHref, + remoteAppIconIds, + remoteAppIconNames, + remoteAppIconTagName, + remoteAppSpriteUrl, +} from './.svg-sprite/index.js' +export type { RemoteAppIconElement, RemoteAppIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone-vite/src/remote-app-icons/svg-sprite.config.js b/integration/apps/standalone-vite/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..bbd9365 --- /dev/null +++ b/integration/apps/standalone-vite/src/remote-app-icons/svg-sprite.config.js @@ -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: 'standalone@vite', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/standalone-vite/src/sprite/index.ts b/integration/apps/standalone-vite/src/sprite/index.ts deleted file mode 100644 index b9c7a54..0000000 --- a/integration/apps/standalone-vite/src/sprite/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { - defineIconsIconElement, - getIconsIconHref, - iconsIconIds, - iconsIconNames, - iconsIconTagName, - iconsSpriteUrl, -} from './.svg-sprite/index.js' -export type { IconsIconElement, IconsIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone-vite/src/style.css b/integration/apps/standalone-vite/src/style.css index 69666bf..16e1b06 100644 --- a/integration/apps/standalone-vite/src/style.css +++ b/integration/apps/standalone-vite/src/style.css @@ -4,7 +4,8 @@ body { font-family: system-ui, sans-serif; } -[data-testid='icon'] { +[data-testid='icon'], +[data-testid='remote-icon'] { width: 64px; height: 64px; color: #16a34a; diff --git a/integration/apps/standalone-webpack/package.json b/integration/apps/standalone-webpack/package.json index 6d562aa..299bfd3 100644 --- a/integration/apps/standalone-webpack/package.json +++ b/integration/apps/standalone-webpack/package.json @@ -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": "tsc --noEmit", "build": "npm run sprites && webpack --mode production", "dev": "npm run sprites && webpack serve --mode development" diff --git a/integration/apps/standalone-webpack/src/app-icons/.gitignore b/integration/apps/standalone-webpack/src/app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/standalone-webpack/src/app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/standalone-webpack/src/app-icons/index.ts b/integration/apps/standalone-webpack/src/app-icons/index.ts new file mode 100644 index 0000000..c1043e4 --- /dev/null +++ b/integration/apps/standalone-webpack/src/app-icons/index.ts @@ -0,0 +1,9 @@ +export { + appIconIds, + appIconNames, + appIconTagName, + appSpriteUrl, + defineAppIconElement, + getAppIconHref, +} from './.svg-sprite/index.js' +export type { AppIconElement, AppIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone-webpack/src/sprite/svg-sprite.config.ts b/integration/apps/standalone-webpack/src/app-icons/svg-sprite.config.ts similarity index 92% rename from integration/apps/standalone-webpack/src/sprite/svg-sprite.config.ts rename to integration/apps/standalone-webpack/src/app-icons/svg-sprite.config.ts index 0d1c666..17b90db 100644 --- a/integration/apps/standalone-webpack/src/sprite/svg-sprite.config.ts +++ b/integration/apps/standalone-webpack/src/app-icons/svg-sprite.config.ts @@ -2,7 +2,7 @@ import { defineSpriteConfig } from '@gromlab/svg-sprites' export default defineSpriteConfig({ mode: 'standalone@webpack', - name: 'icons', + name: 'app', input: '../../../../fixtures/icons/check.svg', generatedNotice: false, }) diff --git a/integration/apps/standalone-webpack/src/generated-contract.typecheck.ts b/integration/apps/standalone-webpack/src/generated-contract.typecheck.ts index 0a988fa..316ba00 100644 --- a/integration/apps/standalone-webpack/src/generated-contract.typecheck.ts +++ b/integration/apps/standalone-webpack/src/generated-contract.typecheck.ts @@ -1,9 +1,15 @@ -import type { IconsIconElement } from './sprite' +import type { AppIconElement } from './app-icons' +import type { RemoteAppIconElement } from './remote-app-icons' -const icon = document.createElement('icons-icon') -const typedIcon: IconsIconElement = icon +const appIcon = document.createElement('app-icon') +const typedAppIcon: AppIconElement = appIcon +const remoteAppIcon = document.createElement('remote-app-icon') +const typedRemoteAppIcon: RemoteAppIconElement = remoteAppIcon -typedIcon.icon = 'check' +typedAppIcon.icon = 'check' +typedRemoteAppIcon.icon = 'check' // @ts-expect-error Generated icon names form a literal union. -typedIcon.icon = 'missing' +typedAppIcon.icon = 'missing' +// @ts-expect-error Generated remote icon names form a literal union. +typedRemoteAppIcon.icon = 'missing' diff --git a/integration/apps/standalone-webpack/src/main.ts b/integration/apps/standalone-webpack/src/main.ts index 8298bf2..a07a9d8 100644 --- a/integration/apps/standalone-webpack/src/main.ts +++ b/integration/apps/standalone-webpack/src/main.ts @@ -1,28 +1,44 @@ import '@gromlab/svg-sprites/viewer/element' import type { SpriteViewerElement } from '@gromlab/svg-sprites/viewer' -import spriteManifest from './sprite/.svg-sprite/svg-sprite.manifest.js' -import { defineIconsIconElement, iconsSpriteUrl } from './sprite' +import appManifest from './app-icons/.svg-sprite/svg-sprite.manifest.js' +import { appSpriteUrl, defineAppIconElement } from './app-icons' +import remoteAppManifest from './remote-app-icons/.svg-sprite/svg-sprite.manifest.js' +import { defineRemoteAppIconElement, remoteAppSpriteUrl } from './remote-app-icons' -const check = spriteManifest.icons.find((icon) => icon.name === 'check') -if (!check || spriteManifest.spriteUrl !== iconsSpriteUrl) { +const appCheck = appManifest.icons.find((icon) => icon.name === 'check') +if (!appCheck || appManifest.spriteUrl !== appSpriteUrl) { throw new Error('Generated Webpack facade and manifest disagree.') } -defineIconsIconElement() +const remoteAppCheck = remoteAppManifest.icons.find((icon) => icon.name === 'check') +if (!remoteAppCheck || remoteAppManifest.spriteUrl !== remoteAppSpriteUrl) { + throw new Error('Generated remote Webpack facade and manifest disagree.') +} + +defineAppIconElement() +defineRemoteAppIconElement() document.querySelector('#app')!.innerHTML = `

Standalone + Webpack

- + > + ` const viewer = document.querySelector('gromlab-sprite-viewer')! viewer.viewerTitle = 'Standalone Webpack Viewer' -viewer.sources = [spriteManifest] +viewer.sources = [appManifest, remoteAppManifest] diff --git a/integration/apps/standalone-webpack/src/remote-app-icons/.gitignore b/integration/apps/standalone-webpack/src/remote-app-icons/.gitignore new file mode 100644 index 0000000..7f3344e --- /dev/null +++ b/integration/apps/standalone-webpack/src/remote-app-icons/.gitignore @@ -0,0 +1,2 @@ +# @generated by @gromlab/svg-sprites. Do not edit. +/.svg-sprite/ diff --git a/integration/apps/standalone-webpack/src/remote-app-icons/index.ts b/integration/apps/standalone-webpack/src/remote-app-icons/index.ts new file mode 100644 index 0000000..cc4b9d9 --- /dev/null +++ b/integration/apps/standalone-webpack/src/remote-app-icons/index.ts @@ -0,0 +1,9 @@ +export { + defineRemoteAppIconElement, + getRemoteAppIconHref, + remoteAppIconIds, + remoteAppIconNames, + remoteAppIconTagName, + remoteAppSpriteUrl, +} from './.svg-sprite/index.js' +export type { RemoteAppIconElement, RemoteAppIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone-webpack/src/remote-app-icons/svg-sprite.config.js b/integration/apps/standalone-webpack/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..7be5178 --- /dev/null +++ b/integration/apps/standalone-webpack/src/remote-app-icons/svg-sprite.config.js @@ -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: 'standalone@webpack', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/standalone-webpack/src/sprite/index.ts b/integration/apps/standalone-webpack/src/sprite/index.ts deleted file mode 100644 index b9c7a54..0000000 --- a/integration/apps/standalone-webpack/src/sprite/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { - defineIconsIconElement, - getIconsIconHref, - iconsIconIds, - iconsIconNames, - iconsIconTagName, - iconsSpriteUrl, -} from './.svg-sprite/index.js' -export type { IconsIconElement, IconsIconName } from './.svg-sprite/index.js' diff --git a/integration/apps/standalone/build.mjs b/integration/apps/standalone/build.mjs index de399bb..a1d341a 100644 --- a/integration/apps/standalone/build.mjs +++ b/integration/apps/standalone/build.mjs @@ -1,17 +1,21 @@ import fs from 'node:fs' fs.rmSync(new URL('./dist/', import.meta.url), { recursive: true, force: true }) -fs.mkdirSync(new URL('./dist/app-icons/', import.meta.url), { recursive: true }) +fs.mkdirSync(new URL('./dist/', import.meta.url), { recursive: true }) fs.copyFileSync(new URL('./index.html', import.meta.url), new URL('./dist/index.html', import.meta.url)) fs.copyFileSync( new URL('../../../dist/viewer-element.js', import.meta.url), new URL('./dist/viewer-element.js', import.meta.url), ) -fs.copyFileSync( - new URL('./src/sprite/.svg-sprite/sprite.svg', import.meta.url), - new URL('./dist/app-icons/sprite.svg', import.meta.url), -) -fs.copyFileSync( - new URL('./src/sprite/.svg-sprite/svg-sprite.manifest.json', import.meta.url), - new URL('./dist/app-icons/manifest.json', import.meta.url), -) + +for (const root of ['app-icons', 'remote-app-icons']) { + fs.mkdirSync(new URL(`./dist/${root}/`, import.meta.url), { recursive: true }) + fs.copyFileSync( + new URL(`./src/${root}/.svg-sprite/sprite.svg`, import.meta.url), + new URL(`./dist/${root}/sprite.svg`, import.meta.url), + ) + fs.copyFileSync( + new URL(`./src/${root}/.svg-sprite/svg-sprite.manifest.json`, import.meta.url), + new URL(`./dist/${root}/manifest.json`, import.meta.url), + ) +} diff --git a/integration/apps/standalone/index.html b/integration/apps/standalone/index.html index b1bd614..dd00965 100644 --- a/integration/apps/standalone/index.html +++ b/integration/apps/standalone/index.html @@ -6,7 +6,7 @@ Standalone sprite fixture @@ -16,12 +16,20 @@ + + +
- + diff --git a/integration/apps/standalone/package.json b/integration/apps/standalone/package.json index 957de0d..1bd3d81 100644 --- a/integration/apps/standalone/package.json +++ b/integration/apps/standalone/package.json @@ -3,7 +3,9 @@ "private": true, "version": "0.0.0", "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", "build": "npm run sprites && node build.mjs", "dev": "npm run build && node ../../scripts/serve-static.mjs dist 4173" }, diff --git a/integration/apps/standalone/src/sprite/svg-sprite.config.json b/integration/apps/standalone/src/app-icons/svg-sprite.config.json similarity index 82% rename from integration/apps/standalone/src/sprite/svg-sprite.config.json rename to integration/apps/standalone/src/app-icons/svg-sprite.config.json index 2fedb7e..cce58de 100644 --- a/integration/apps/standalone/src/sprite/svg-sprite.config.json +++ b/integration/apps/standalone/src/app-icons/svg-sprite.config.json @@ -1,6 +1,6 @@ { "mode": "standalone", - "name": "app-icons", + "name": "app", "input": "../../../../fixtures/icons/check.svg", "generatedNotice": false } diff --git a/integration/apps/standalone/src/remote-app-icons/svg-sprite.config.js b/integration/apps/standalone/src/remote-app-icons/svg-sprite.config.js new file mode 100644 index 0000000..25182b2 --- /dev/null +++ b/integration/apps/standalone/src/remote-app-icons/svg-sprite.config.js @@ -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: 'standalone', + source: 'remote', + input: manifestUrl, +} diff --git a/integration/apps/svelte-vite/package.json b/integration/apps/svelte-vite/package.json index cbfe7ff..b49ed09 100644 --- a/integration/apps/svelte-vite/package.json +++ b/integration/apps/svelte-vite/package.json @@ -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": "svelte-check --tsconfig ./tsconfig.json", "build": "npm run sprites && svelte-check --tsconfig ./tsconfig.json && vite build", "dev": "npm run sprites && vite" diff --git a/integration/apps/svelte-vite/src/App.svelte b/integration/apps/svelte-vite/src/App.svelte index 62123f0..dc8f6aa 100644 --- a/integration/apps/svelte-vite/src/App.svelte +++ b/integration/apps/svelte-vite/src/App.svelte @@ -1,10 +1,12 @@