UNPKG

@stephansama/astro-iconify-svgmap

Version:

Astro integration for generating iconify svgmaps for ssg sites

217 lines (155 loc) 6.06 kB
--- name: astro-iconify-svgmap description: > Astro integration that generates optimized SVG sprite maps from @iconify-json/* icon packs for SSG sites. Add createIntegration() to astro.config.mjs, import virtual:iconify-svgmap in your base layout to activate the plugin, then call getIcon(pack, name) in .astro components to register icons and get <use> hrefs. Use iconifyRootDirectory for monorepos where node_modules is not at the project root. type: framework requires: - astro library: "@stephansama/astro-iconify-svgmap" library_version: "1.0.14" sources: - stephansama/packages:core/astro-iconify-svgmap/src/index.ts - stephansama/packages:core/astro-iconify-svgmap/src/get.ts - stephansama/packages:core/astro-iconify-svgmap/src/type.ts - stephansama/packages:core/astro-iconify-svgmap/src/const.ts --- # astro-iconify-svgmap Generates SVG sprite maps from Iconify icon packs at build time and serves them during dev. Icons are registered lazily via `getIcon()` and assembled into per-pack sprite files. ## Setup 1. Install the integration and at least one `@iconify-json/*` pack: ```sh pnpm add @stephansama/astro-iconify-svgmap @iconify-json/mdi ``` 1. Add to `astro.config.mjs`: ```js import { createIntegration } from "@stephansama/astro-iconify-svgmap"; import { defineConfig } from "astro/config"; export default defineConfig({ integrations: [createIntegration()], }); ``` 1. Import the virtual module in your base layout (this activates the Vite plugin): ```astro --- // src/layouts/BaseLayout.astro import "virtual:iconify-svgmap"; --- ``` 1. Use icons in any `.astro` component: ```astro --- import { getIcon } from "@stephansama/astro-iconify-svgmap/get"; const iconHref = await getIcon("mdi", "home"); --- <svg width="24" height="24"> <use href={iconHref}></use> </svg> ``` ## Core Patterns ### Basic icon rendering ```astro --- import { getIcon } from "@stephansama/astro-iconify-svgmap/get"; const href = await getIcon("mdi", "account"); --- <svg width="24" height="24" aria-hidden="true"> <use href={href}></use> </svg> ``` `getIcon(pack, name)` returns `/<pack>.svg#<name>` a fragment reference into the generated sprite. On the server it also registers the icon in the usage tracking file so the build step knows to include it in the sprite. ### Monorepo setup with iconifyRootDirectory ```js // astro.config.mjs inside a pnpm monorepo where icons are in the workspace root import { createIntegration } from "@stephansama/astro-iconify-svgmap"; import { defineConfig } from "astro/config"; export default defineConfig({ integrations: [ createIntegration({ iconifyRootDirectory: new URL("../../", import.meta.url), }), ], }); ``` `iconifyRootDirectory` is a `URL` pointing to the directory whose `node_modules` contains the `@iconify-json/*` packages. Defaults to the Astro project root. ### Custom output directory ```js createIntegration({ outDir: "public/icons" }); ``` Sprites are written to `<outDir>/<pack>.svg` at build time. Default is `public`. ### noto-emoji pack alias `getIcon('noto-emoji', 'name')` automatically resolves to the `noto` pack slug. No special config needed. ## Common Mistakes ### CRITICAL No @iconify-json/\* packages installed Wrong: ```sh pnpm add @stephansama/astro-iconify-svgmap # No icon pack installed ``` ```astro --- const href = await getIcon("mdi", "home"); // loadIcons finds no @iconify-json/mdi sprite is empty --- ``` Correct: ```sh pnpm add @iconify-json/mdi ``` The integration scans `node_modules/@iconify-json/*` to build sprite data. Without the corresponding pack installed, icons silently produce broken `<use>` references at build time. Source: `core/astro-iconify-svgmap/src/utilities.ts` ### CRITICAL virtual:iconify-svgmap not imported in base layout Wrong: ```astro --- // BaseLayout.astro virtual module never imported import { getIcon } from "@stephansama/astro-iconify-svgmap/get"; const href = await getIcon("mdi", "home"); --- ``` Correct: ```astro --- import "virtual:iconify-svgmap"; --- ``` The `virtual:iconify-svgmap` import is what causes Vite to resolve the virtual module and activate the plugin's `load()` hook, which loads all icon collections into memory. Without this import somewhere in the build graph, the plugin never initializes and `getIcon()` produces hrefs with no corresponding sprite data at build time. Source: `core/astro-iconify-svgmap/src/index.ts` ### HIGH Using createPlugin instead of createIntegration in astro.config.mjs Wrong: ```js import createPlugin from "@stephansama/astro-iconify-svgmap"; import { defineConfig } from "astro/config"; export default defineConfig({ vite: { plugins: [createPlugin()], // bypasses astro:build:done hook }, }); ``` Correct: ```js import { createIntegration } from "@stephansama/astro-iconify-svgmap"; export default defineConfig({ integrations: [createIntegration()], }); ``` `createPlugin` is the raw Vite plugin it handles dev-time sprite serving but does not register the `astro:build:done` hook that writes the final sprite files to `outDir`. Using `createPlugin` directly means icons work in dev but sprites are missing in the production build. Always use `createIntegration` in Astro projects. Source: `core/astro-iconify-svgmap/src/index.ts:createIntegration` ### HIGH iconifyRootDirectory not set in monorepo Wrong: ```js // apps/site/astro.config.mjs in a monorepo // @iconify-json/mdi is in the workspace root node_modules, not apps/site/node_modules createIntegration(); // looks in apps/site/node_modules finds nothing ``` Correct: ```js createIntegration({ iconifyRootDirectory: new URL("../../", import.meta.url), }); ``` The default icon discovery path is relative to the Astro project root. In a pnpm monorepo, `@iconify-json/*` packages are typically hoisted to the workspace root. Pass `iconifyRootDirectory` as a `URL` pointing to the directory that contains the `node_modules/@iconify-json/` tree. Source: `core/astro-iconify-svgmap/src/type.ts`