├── .nvmrc ├── README.md ├── demo ├── .gitignore ├── public │ ├── robots.txt │ └── favicon.ico ├── tsconfig.json ├── src │ ├── env.d.ts │ ├── icons │ │ ├── annotation.svg │ │ ├── adjustment.svg │ │ └── logos │ │ │ ├── deno.svg │ │ │ ├── alpine.svg │ │ │ └── alpine-multi-color.svg │ ├── layouts │ │ └── base.astro │ └── pages │ │ ├── map.astro │ │ └── index.astro ├── astro.config.ts ├── sandbox.config.json ├── package.json └── README.md ├── packages ├── service │ ├── .gitignore │ ├── vercel.json │ ├── package.json │ └── api │ │ └── v1 │ │ └── icon.ts ├── core │ ├── typings │ │ ├── global.d.ts │ │ ├── virtual.d.ts │ │ ├── iconify.d.ts │ │ └── integration.d.ts │ ├── components │ │ ├── cache.ts │ │ ├── index.ts │ │ └── Icon.astro │ ├── src │ │ ├── index.ts │ │ ├── loaders │ │ │ ├── loadLocalCollection.ts │ │ │ └── loadIconifyCollections.ts │ │ └── vite-plugin-astro-icon.ts │ ├── tsconfig.json │ ├── package.json │ ├── README.md │ └── CHANGELOG.md └── www │ ├── tsconfig.json │ ├── src │ ├── env.d.ts │ ├── assets │ │ └── houston.webp │ └── content │ │ ├── config.ts │ │ └── docs │ │ ├── 404.md │ │ ├── acknowledgements.mdx │ │ ├── index.mdx │ │ ├── guides │ │ ├── styling.mdx │ │ ├── deployment.mdx │ │ ├── customization.mdx │ │ ├── components.mdx │ │ └── upgrade │ │ │ └── v1.mdx │ │ ├── reference │ │ └── configuration.mdx │ │ └── getting-started.mdx │ ├── .gitignore │ ├── package.json │ ├── public │ └── favicon.svg │ ├── astro.config.mjs │ └── README.md ├── .prettierignore ├── pnpm-workspace.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug.yml └── workflows │ ├── release.yml │ └── ci.yml ├── tsconfig.base.json ├── .changeset ├── config.json └── README.md ├── package.json ├── LICENSE └── .gitignore /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.18.0 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ./packages/core/README.md -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .astro 3 | -------------------------------------------------------------------------------- /packages/service/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .github 2 | node_modules 3 | -------------------------------------------------------------------------------- /demo/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | - "demo" 4 | -------------------------------------------------------------------------------- /packages/core/typings/global.d.ts: -------------------------------------------------------------------------------- 1 | interface Error { 2 | hint?: string; 3 | } 4 | -------------------------------------------------------------------------------- /packages/www/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } 4 | -------------------------------------------------------------------------------- /demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natemoo-re/astro-icon/HEAD/demo/public/favicon.ico -------------------------------------------------------------------------------- /packages/core/components/cache.ts: -------------------------------------------------------------------------------- 1 | export const cache = new WeakMap>(); 2 | -------------------------------------------------------------------------------- /packages/www/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /packages/www/src/assets/houston.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natemoo-re/astro-icon/HEAD/packages/www/src/assets/houston.webp -------------------------------------------------------------------------------- /packages/core/components/index.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore Icon.astro is untyped unless loaded by language tools 2 | export { default as Icon } from "./Icon.astro"; 3 | -------------------------------------------------------------------------------- /demo/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 📘 Documentation 4 | url: https://astroicon.dev 5 | about: Read the official documentation 6 | -------------------------------------------------------------------------------- /demo/astro.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "astro/config"; 2 | import icon from "astro-icon"; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | integrations: [icon()], 7 | }); 8 | -------------------------------------------------------------------------------- /packages/core/typings/virtual.d.ts: -------------------------------------------------------------------------------- 1 | declare module "virtual:astro-icon" { 2 | const icons: import("./integration").AstroIconCollectionMap; 3 | export default icons; 4 | export const config: import("./integration").IntegrationOptions; 5 | } 6 | -------------------------------------------------------------------------------- /packages/www/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from "astro:content"; 2 | import { docsSchema } from "@astrojs/starlight/schema"; 3 | 4 | export const collections = { 5 | docs: defineCollection({ schema: docsSchema() }), 6 | }; 7 | -------------------------------------------------------------------------------- /demo/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "infiniteLoopProtection": true, 3 | "hardReloadOnChange": false, 4 | "view": "browser", 5 | "template": "node", 6 | "container": { 7 | "port": 3000, 8 | "startScript": "start", 9 | "node": "14" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "emitDeclarationOnly": false, 5 | "strict": true, 6 | "moduleResolution": "node", 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "verbatimModuleSyntax": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /demo/src/icons/annotation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/service/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { "source": "/v1", "destination": "/api/v1/icon" }, 4 | { "source": "/v1/:pack", "destination": "/api/v1/icon" }, 5 | { "source": "/v1/:pack/:name", "destination": "/api/v1/icon" } 6 | ], 7 | "cleanUrls": true, 8 | "trailingSlash": false 9 | } 10 | -------------------------------------------------------------------------------- /demo/src/layouts/base.astro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Astro Icon 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/www/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Not found 3 | template: splash 4 | editUrl: false 5 | hero: 6 | title: "404" 7 | tagline: Houston, we have a problem. We couldn’t find that page.
Check the URL or try using the search bar. 8 | actions: 9 | - text: Go home 10 | icon: right-arrow 11 | link: / 12 | variant: primary 13 | --- 14 | -------------------------------------------------------------------------------- /demo/src/icons/adjustment.svg: -------------------------------------------------------------------------------- 1 | 2 | Adjustment 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/core/typings/iconify.d.ts: -------------------------------------------------------------------------------- 1 | import type { runSVGO } from "@iconify/tools"; 2 | 3 | export type SVGOOptions = Omit[1], "keepShapes">; 4 | 5 | export type { IconifyJSON } from "@iconify/types"; 6 | export type { SVG } from "@iconify/tools"; 7 | export type { Color } from "@iconify/utils/lib/colors/types"; 8 | export type { AutoInstall } from "@iconify/utils/lib/loader/types"; 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "natemoo-re/astro-icon" } 6 | ], 7 | "commit": false, 8 | "linked": [], 9 | "access": "public", 10 | "baseBranch": "main", 11 | "updateInternalDependencies": "patch", 12 | "ignore": ["www", "service", "demo"] 13 | } 14 | -------------------------------------------------------------------------------- /demo/src/pages/map.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | import Base from "../layouts/base.astro"; 4 | --- 5 | 6 | 7 |

Welcome to Astro Icon!

8 | 9 | {Array.from({ length: 5 }).map(() => )} 10 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /packages/core/typings/integration.d.ts: -------------------------------------------------------------------------------- 1 | import type { IconifyJSON, SVGOOptions } from "./iconify"; 2 | 3 | export type IntegrationOptions = { 4 | include?: Record; 5 | /** 6 | * @default "src/icons" 7 | */ 8 | iconDir?: string; 9 | /** 10 | * @default { plugins: ['preset-default'] } 11 | */ 12 | svgoOptions?: SVGOOptions; 13 | }; 14 | 15 | export type IconCollection = IconifyJSON; 16 | export type AstroIconCollectionMap = Record; 17 | -------------------------------------------------------------------------------- /packages/www/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "www", 3 | "private": true, 4 | "type": "module", 5 | "version": "0.0.1", 6 | "scripts": { 7 | "dev": "astro dev", 8 | "start": "astro dev", 9 | "build": "astro check && astro build", 10 | "preview": "astro preview", 11 | "astro": "astro" 12 | }, 13 | "dependencies": { 14 | "@astrojs/check": "^0.3.4", 15 | "@astrojs/starlight": "^0.15.1", 16 | "astro": "^4.0.7", 17 | "sharp": "^0.32.5", 18 | "typescript": "^5.0.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview" 10 | }, 11 | "dependencies": { 12 | "@iconify-json/bi": "^1.1.15", 13 | "@iconify-json/fe": "^1.1.6", 14 | "@iconify-json/ic": "^1.1.13", 15 | "@iconify-json/ri": "^1.1.5" 16 | }, 17 | "devDependencies": { 18 | "astro": "^4.0.7", 19 | "astro-icon": "workspace:*" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/www/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "service", 3 | "private": true, 4 | "version": "0.1.0", 5 | "author": { 6 | "name": "Nate Moore", 7 | "email": "nate@natemoo.re", 8 | "url": "https://twitter.com/n_moore" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/natemoo-re/astro-icon.git", 13 | "directory": "packages/service" 14 | }, 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/natemoo-re/astro-icon/issues" 18 | }, 19 | "homepage": "https://github.com/natemoo-re/astro-icon#readme", 20 | "dependencies": { 21 | "@iconify/json": "^1.1.461", 22 | "@iconify/json-tools": "^1.0.10", 23 | "etag": "^1.8.1" 24 | }, 25 | "devDependencies": { 26 | "@vercel/node": "^1.12.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { IntegrationOptions } from "../typings/integration"; 2 | import { createPlugin } from "./vite-plugin-astro-icon.js"; 3 | import type { AstroIntegration } from "astro"; 4 | 5 | export default function createIntegration( 6 | opts: IntegrationOptions = {}, 7 | ): AstroIntegration { 8 | return { 9 | name: "astro-icon", 10 | hooks: { 11 | "astro:config:setup"({ updateConfig, config, logger }) { 12 | const external = 13 | config.output === "static" ? ["@iconify-json/*"] : undefined; 14 | const { root, output } = config; 15 | updateConfig({ 16 | vite: { 17 | plugins: [createPlugin(opts, { root, output, logger })], 18 | ssr: { 19 | external, 20 | }, 21 | }, 22 | }); 23 | }, 24 | }, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "build": "pnpm --filter astro-icon --filter www run build", 8 | "dev": "pnpm -r run dev", 9 | "lint": "prettier \"**/*.{js,ts,md,json}\"", 10 | "version": "changeset version && pnpm install --no-frozen-lockfile --lockfile-only" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/natemoo-re/astro-icon.git" 15 | }, 16 | "keywords": [], 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/natemoo-re/astro-icon/issues" 20 | }, 21 | "homepage": "https://github.com/natemoo-re/astro-icon#readme", 22 | "packageManager": "pnpm@8.11.0", 23 | "dependencies": { 24 | "@changesets/changelog-github": "^0.4.2", 25 | "@changesets/cli": "^2.18.1" 26 | }, 27 | "devDependencies": { 28 | "prettier": "^3.1.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/acknowledgements.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Acknowledgements 3 | description: Learn how to start building your next documentation site with Starlight by Astro. 4 | prev: false 5 | next: false 6 | --- 7 | 8 | Originally built by Nate Moore ([@natemoo-re](https://github.com/natemoo-re)) as an experimental package, Astro Icon would not be what it is today without the support of the larger Astro community. 9 | 10 | A very special thank you to Michael Stramel ([@stramel](https://github.com/stramel)) for his help maintaining Astro Icon, spear-heading the v1 release, and providing great user support during the transition to v1. 11 | 12 | ## Libraries 13 | 14 | Astro Icon would not be possible without [Iconify](https://iconify.design/), an open source effort to distribute thousands of icon sets in a normalized format. 15 | 16 | Please consider [sponsoring Iconify](https://iconify.design/sponsors/) to support this ongoing effort. 17 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "include": ["src", "typings"], 4 | "compilerOptions": { 5 | "allowJs": true, 6 | "module": "ES2022", 7 | "outDir": "./dist", 8 | "target": "ES2021", 9 | "jsx": "preserve", 10 | "baseUrl": "./" 11 | }, 12 | // NEW: Options for file/directory watching 13 | "watchOptions": { 14 | // Use native file system events for files and directories 15 | "watchFile": "useFsEvents", 16 | "watchDirectory": "useFsEvents", 17 | // Poll files for updates more frequently 18 | // when they're updated a lot. 19 | "fallbackPolling": "dynamicPriority", 20 | // Don't coalesce watch notification 21 | "synchronousWatchDirectory": true, 22 | // Finally, two additional settings for reducing the amount of possible 23 | // files to track work from these directories 24 | "excludeDirectories": ["**/node_modules", "_build"], 25 | "excludeFiles": [] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Astro Icon 3 | description: Astro Icon simplifies working with icons in Astro 4 | template: splash 5 | editUrl: false 6 | lastUpdated: false 7 | hero: 8 | tagline: Icons made easy, powered by Astro 9 | actions: 10 | - text: Get Started 11 | link: /getting-started/ 12 | icon: right-arrow 13 | variant: primary 14 | - text: View Repo 15 | link: https://github.com/natemoo-re/astro-icon 16 | icon: external 17 | --- 18 | 19 | import { Card, CardGrid } from '@astrojs/starlight/components'; 20 | 21 | ## Next steps 22 | 23 | 24 | 25 | Automatically embed custom `svg` icons 26 | 27 | 28 | Support for all [`@iconify-json/*`](https://iconify.design/) packages 29 | 30 | 31 | Deduplicated sprites with zero overhead 32 | 33 | 34 | Fully dynamic icon references without imports 35 | 36 | 37 | -------------------------------------------------------------------------------- /packages/www/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import starlight from '@astrojs/starlight'; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | integrations: [ 7 | starlight({ 8 | title: 'Astro Icon', 9 | social: { 10 | github: 'https://github.com/natemoo-re/astro-icon', 11 | }, 12 | sidebar: [ 13 | { 14 | label: 'Start Here', 15 | items: [ 16 | { label: 'Getting Started', link: '/getting-started/' }, 17 | { label: 'Upgrade to v1', link: '/guides/upgrade/v1/' }, 18 | { label: 'Acknowledgements', link: '/acknowledgements/' }, 19 | ], 20 | }, 21 | { 22 | label: 'Guides', 23 | items: [ 24 | { label: 'Customizing Icons', link: '/guides/customization/' }, 25 | { label: 'Components', link: '/guides/components/' }, 26 | { label: 'CSS & Styling', link: '/guides/styling/' }, 27 | { label: 'Deployment', link: '/guides/deployment/' }, 28 | ], 29 | }, 30 | { 31 | label: 'Reference', 32 | autogenerate: { directory: 'reference' }, 33 | }, 34 | ], 35 | }), 36 | ], 37 | }); 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | 8 | defaults: 9 | run: 10 | shell: bash 11 | 12 | jobs: 13 | changelog: 14 | name: Changelog PR or Release 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: pnpm/action-setup@v4 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: 18 22 | registry-url: 'https://registry.npmjs.org' 23 | cache: 'pnpm' 24 | env: 25 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 26 | - run: pnpm install 27 | - run: pnpm --filter astro-icon run build 28 | - name: Create Release Pull Request or Publish 29 | id: changesets 30 | uses: changesets/action@v1 31 | with: 32 | version: pnpm run version 33 | publish: pnpm changeset publish 34 | commit: 'chore: release' 35 | title: 'chore: release' 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 40 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/guides/styling.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS & Styling 3 | description: Learn how to style your icons with custom CSS. 4 | --- 5 | 6 | You can style your icons with custom CSS. 7 | 8 | ## Custom CSS styles 9 | 10 | Customize the styles applied to every icon by using the `[data-icon]` attribute selector. 11 | 12 | ```astro mark="Icon" mark="[data-icon]" 13 | 14 | 15 | 16 | 17 | 23 | ``` 24 | 25 | Customize the styles applied to a single icon by using the `[data-icon="name"]` attribute selector. 26 | 27 | ```astro mark="Icon" mark="logo" mark="[data-icon=\"logo\"]" 28 | 29 | 30 | 36 | ``` 37 | 38 | ## Tailwind CSS 39 | 40 | Tailwind CSS support in Astro projects is provided by the [Astro Tailwind integration](https://docs.astro.build/en/guides/integrations-guide/tailwind/). 41 | The `Icon` component automatically passes the `class` prop through to the underlying `svg` element. 42 | 43 | ```astro mark="class=\"text-xl text-emerald-700\"" 44 | 45 | ``` 46 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/guides/deployment.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deployment 3 | description: Learn how to optimize your deployments with Astro Icon. 4 | --- 5 | 6 | Astro Icon supports every deployment method that Astro supports. Refer to the official [Deploy your Astro Site](https://docs.astro.build/en/guides/deploy/) guide for specific instructions. 7 | 8 | ## Rendering Modes 9 | 10 | Astro projects support multiple [Rendering Modes](https://docs.astro.build/en/core-concepts/rendering-modes/), pages, routes, and API endpoints can be either [pre-rendered at build time](https://docs.astro.build/en/core-concepts/rendering-modes/#pre-rendered) or [rendered on demand by a server](https://docs.astro.build/en/core-concepts/rendering-modes/#on-demand-rendered) when a route is requested. 11 | 12 | ### Pre-rendered 13 | 14 | Astro projects that are entirely pre-rendered do not need any special configuration to use Astro Icon. 15 | 16 | ### On-demand rendered 17 | 18 | Astro projects that have [enabled on-demand server rendering](https://docs.astro.build/en/guides/server-side-rendering/#enable-on-demand-server-rendering) should take special care when using Astro Icon. 19 | 20 | By default, all `@iconify-json/*` packages will be bundled into your server code, potentially bloating your server JavaScript bundles. 21 | 22 | For complete control over the size of your bundle, it is **highly recommended** to [configure the `include` option](/reference/configuration#include) to enable only your required icons. 23 | 24 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astro-icon", 3 | "version": "1.1.5", 4 | "type": "module", 5 | "types": "./dist/index.d.ts", 6 | "exports": { 7 | ".": { 8 | "types": "./dist/index.d.ts", 9 | "default": "./dist/index.js" 10 | }, 11 | "./components": "./components/index.ts" 12 | }, 13 | "files": [ 14 | "components", 15 | "dist", 16 | "typings" 17 | ], 18 | "scripts": { 19 | "build": "tsc", 20 | "dev": "tsc --watch", 21 | "start": "pnpm run dev" 22 | }, 23 | "author": { 24 | "name": "Nate Moore", 25 | "email": "nate@natemoo.re", 26 | "url": "https://twitter.com/n_moore" 27 | }, 28 | "keywords": [ 29 | "astro", 30 | "astro-integration", 31 | "astro-component", 32 | "image", 33 | "images", 34 | "icon", 35 | "icons", 36 | "iconify", 37 | "optimization" 38 | ], 39 | "repository": { 40 | "type": "git", 41 | "url": "git+https://github.com/natemoo-re/astro-icon.git", 42 | "directory": "packages/core" 43 | }, 44 | "license": "MIT", 45 | "bugs": { 46 | "url": "https://github.com/natemoo-re/astro-icon/issues" 47 | }, 48 | "homepage": "https://github.com/natemoo-re/astro-icon#readme", 49 | "dependencies": { 50 | "@iconify/tools": "^4.0.5", 51 | "@iconify/types": "^2.0.0", 52 | "@iconify/utils": "^2.1.30" 53 | }, 54 | "devDependencies": { 55 | "@types/node": "^18.18.0", 56 | "astro": "^4.0.0", 57 | "typescript": "^5.0.4", 58 | "vite": "^5.0.0" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # Astro Starter Kit: Minimal 2 | 3 | ``` 4 | npm init astro -- --template minimal 5 | ``` 6 | 7 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal) 8 | 9 | > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! 10 | 11 | ## 🚀 Project Structure 12 | 13 | Inside of your Astro project, you'll see the following folders and files: 14 | 15 | ``` 16 | / 17 | ├── public/ 18 | ├── src/ 19 | │ └── pages/ 20 | │ └── index.astro 21 | └── package.json 22 | ``` 23 | 24 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 25 | 26 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 27 | 28 | Any static assets, like images, can be placed in the `public/` directory. 29 | 30 | ## 🧞 Commands 31 | 32 | All commands are run from the root of the project, from a terminal: 33 | 34 | | Command | Action | 35 | | :---------------- | :------------------------------------------- | 36 | | `npm install` | Installs dependencies | 37 | | `npm run dev` | Starts local dev server at `localhost:3000` | 38 | | `npm run build` | Build your production site to `./dist/` | 39 | | `npm run preview` | Preview your build locally, before deploying | 40 | 41 | ## 👀 Want to learn more? 42 | 43 | Feel free to check [our documentation](https://github.com/withastro/astro) or jump into our [Discord server](https://astro.build/chat). 44 | -------------------------------------------------------------------------------- /demo/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | import Base from "../layouts/base.astro"; 4 | 5 | const icon = "adjustment"; 6 | --- 7 | 8 | 9 |

Welcome to Astro Icon!

10 | 11 |

12 | The Icon component will optimize and inline any SVG file inside 13 | of src/icons/ 14 |

15 | 16 |
17 |

Local Icons

18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 |

Automatic Icons from Iconify

31 |

32 | If you can find it on Icones, you can 33 | render it here! 34 |

35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 62 | -------------------------------------------------------------------------------- /packages/www/README.md: -------------------------------------------------------------------------------- 1 | # Astro Icon Docs 2 | 3 | [![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) 4 | 5 | ## 🚀 Project Structure 6 | 7 | Inside of this Astro + Starlight project, you'll see the following folders and files: 8 | 9 | ``` 10 | . 11 | ├── public/ 12 | ├── src/ 13 | │ ├── assets/ 14 | │ ├── content/ 15 | │ │ ├── docs/ 16 | │ │ └── config.ts 17 | │ └── env.d.ts 18 | ├── astro.config.mjs 19 | ├── package.json 20 | └── tsconfig.json 21 | ``` 22 | 23 | Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. 24 | 25 | Images can be added to `src/assets/` and embedded in Markdown with a relative link. 26 | 27 | Static assets, like favicons, can be placed in the `public/` directory. 28 | 29 | ## 🧞 Commands 30 | 31 | All commands are run from the root of the project, from a terminal: 32 | 33 | | Command | Action | 34 | | :------------------------ | :----------------------------------------------- | 35 | | `npm install` | Installs dependencies | 36 | | `npm run dev` | Starts local dev server at `localhost:4321` | 37 | | `npm run build` | Build your production site to `./dist/` | 38 | | `npm run preview` | Preview your build locally, before deploying | 39 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | 40 | | `npm run astro -- --help` | Get help using the Astro CLI | 41 | 42 | ## 👀 Want to learn more? 43 | 44 | Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). 45 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | pull_request: 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.ref }} 11 | cancel-in-progress: true 12 | 13 | defaults: 14 | run: 15 | shell: bash 16 | 17 | jobs: 18 | lint: 19 | name: Lint 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: pnpm/action-setup@v4 24 | - uses: actions/setup-node@v4 25 | with: 26 | node-version: 18 27 | cache: 'pnpm' 28 | - run: pnpm install 29 | 30 | # Lint autofix cannot run on forks, so just skip those! See https://github.com/wearerequired/lint-action/issues/13 31 | - name: Lint (External) 32 | if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login != github.repository_owner }} 33 | run: pnpm run lint 34 | 35 | # Otherwise, run lint autofixer 36 | - name: Lint 37 | if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }} 38 | uses: wearerequired/lint-action@v1.10.0 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | with: 42 | prettier: true 43 | auto_fix: true 44 | git_name: github-actions[bot] 45 | git_email: github-actions[bot]@users.noreply.github.com 46 | commit_message: 'chore(lint): ${linter} fix' 47 | github_token: ${{ secrets.GITHUB_TOKEN }} 48 | neutral_check_on_warning: true 49 | 50 | smoke: 51 | name: Smoke Test 52 | runs-on: ubuntu-latest 53 | steps: 54 | - uses: actions/checkout@v4 55 | - uses: pnpm/action-setup@v4 56 | - uses: actions/setup-node@v4 57 | with: 58 | node-version: 18 59 | cache: 'pnpm' 60 | - run: pnpm install 61 | - run: pnpm -r build 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: "Bug Report" 2 | description: Report an issue or possible bug 3 | labels: [] 4 | assignees: [] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ## Quick Checklist 10 | Thank you for taking the time to file a bug report! Please fill out this form as completely as possible. 11 | 12 | ✅ I am using the **latest version of Astro Icon**. 13 | ✅ Astro Icon has been added to my `astro.config.mjs` file as an `integration`. 14 | ✅ I have installed the corresponding `@iconify-json/*` packages. 15 | ✅ I am using the **latest version of Astro** and all plugins. 16 | ✅ I am using a version of Node that Astro supports (`>=18.14.1`) 17 | - type: input 18 | id: astro-icon 19 | attributes: 20 | label: What version of `astro-icon` are you using? 21 | placeholder: v1.0.0 22 | - type: textarea 23 | id: astro-info 24 | attributes: 25 | label: Astro Info 26 | description: Run the command `astro info` in your terminal and paste the output here. Please review the data before submitting in case there is any sensitive information you don't want to share. 27 | render: block 28 | validations: 29 | required: true 30 | - type: input 31 | id: browser 32 | attributes: 33 | label: If this issue only occurs in one browser, which browser is a problem? 34 | placeholder: Chrome, Firefox, Safari 35 | - type: textarea 36 | id: bug-description 37 | attributes: 38 | label: Describe the Bug 39 | description: A clear and concise description of what the bug is. 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: bug-expectation 44 | attributes: 45 | label: What's the expected result? 46 | description: Describe what you expect to happen. 47 | validations: 48 | required: true 49 | - type: input 50 | id: bug-reproduction 51 | attributes: 52 | label: Link to Minimal Reproducible Example 53 | description: 'Use [astro.new](https://astro.new) to create a minimal reproduction of the problem. **A minimal reproduction is required** so that we can help debug your issue!' 54 | placeholder: 'https://stackblitz.com/abcd1234' 55 | validations: 56 | required: true 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2021 Nate Moore 2 | 3 | Permission is hereby granted, free of 4 | charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, copy, modify, merge, 7 | publish, distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to the 9 | following conditions: 10 | 11 | The above copyright notice and this permission notice 12 | (including the next paragraph) shall be included in all copies or substantial 13 | portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 18 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | --- 24 | 25 | Some portions of this code adapted from https://github.com/developit/htmlParser 26 | 27 | The MIT License (MIT) 28 | 29 | Copyright (c) 2013 Jason Miller 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy of 32 | this software and associated documentation files (the "Software"), to deal in 33 | the Software without restriction, including without limitation the rights to 34 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 35 | the Software, and to permit persons to whom the Software is furnished to do so, 36 | subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all 39 | copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 43 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 44 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 45 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 46 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 47 | -------------------------------------------------------------------------------- /packages/service/api/v1/icon.ts: -------------------------------------------------------------------------------- 1 | import { VercelApiHandler } from "@vercel/node"; 2 | import { Collection, SVG } from "@iconify/json-tools"; 3 | import etag from "etag"; 4 | 5 | const packAliases = new Map([ 6 | ["logo", "fa-brands"], 7 | ["radix", "radix-icons"], 8 | ]); 9 | 10 | const handler: VercelApiHandler = async (req, res) => { 11 | const reqOrigin = req.headers["origin"]; 12 | const reqEtag = req.headers["if-none-match"]; 13 | res.setHeader("Access-Control-Allow-Origin", reqOrigin || "*"); 14 | res.setHeader("Cache-Control", "s-maxage=59, stale-while-revalidate=299"); 15 | res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS"); 16 | let { pack, name } = req.query; 17 | if (!pack) { 18 | res.status(400).send(`Bad Request: No "pack" query param detected`); 19 | return; 20 | } 21 | if (Array.isArray(pack)) { 22 | res.status(400).send(`Bad Request: "pack" cannot be passed multiple times`); 23 | return; 24 | } 25 | if (Array.isArray(name)) { 26 | res.status(400).send(`Bad Request: "name" cannot be passed multiple times`); 27 | return; 28 | } 29 | if (!name && pack.includes(":")) { 30 | const [prefix, ...parts] = pack.split(":"); 31 | pack = prefix; 32 | name = parts.join(":"); 33 | } 34 | if (!pack && name?.includes(":")) { 35 | const [prefix, ...parts] = name.split(":"); 36 | pack = prefix; 37 | name = parts.join(":"); 38 | } 39 | 40 | if (packAliases.has(pack)) { 41 | pack = packAliases.get(pack); 42 | } 43 | 44 | let collection = new Collection(); 45 | if (!collection.loadIconifyCollection(pack)) { 46 | // TODO: fuzzy match to provide more helpful error? 47 | res.status(404).send(`Not Found: pack "${pack}"`); 48 | return; 49 | } 50 | 51 | if (!name) { 52 | const icons = collection.getIcons(); 53 | res.setHeader("Content-Type", "application/json"); 54 | const body = JSON.stringify(Object.keys(icons.icons)); 55 | const resEtag = etag(body); 56 | if (reqEtag === resEtag) { 57 | res.status(304).end(); 58 | } else { 59 | res.setHeader("ETag", resEtag); 60 | res.status(200).send(body); 61 | } 62 | return; 63 | } 64 | 65 | const data = collection.getIconData(name); 66 | if (!data) { 67 | res.status(404).send(`Not Found: "${name}" in pack "${pack}"`); 68 | return; 69 | } 70 | const svg = new SVG(data).getSVG({}); 71 | const resEtag = etag(svg); 72 | if (reqEtag === resEtag) { 73 | res.status(304).end(); 74 | } else { 75 | res.setHeader("ETag", resEtag); 76 | res.setHeader("Content-Type", "image/svg+xml"); 77 | res.status(200).send(svg); 78 | } 79 | }; 80 | 81 | export default handler; 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist 3 | 4 | # dependencies 5 | node_modules/ 6 | .snowpack/ 7 | 8 | # logs 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # environment variables 14 | .env 15 | .env.production 16 | 17 | # macOS-specific files 18 | .DS_Store 19 | # Logs 20 | logs 21 | *.log 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | lerna-debug.log* 26 | .pnpm-debug.log* 27 | 28 | # Diagnostic reports (https://nodejs.org/api/report.html) 29 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 30 | 31 | # Runtime data 32 | pids 33 | *.pid 34 | *.seed 35 | *.pid.lock 36 | 37 | # Directory for instrumented libs generated by jscoverage/JSCover 38 | lib-cov 39 | 40 | # Coverage directory used by tools like istanbul 41 | coverage 42 | *.lcov 43 | 44 | # nyc test coverage 45 | .nyc_output 46 | 47 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 48 | .grunt 49 | 50 | # Bower dependency directory (https://bower.io/) 51 | bower_components 52 | 53 | # node-waf configuration 54 | .lock-wscript 55 | 56 | # Compiled binary addons (https://nodejs.org/api/addons.html) 57 | build/Release 58 | 59 | # Dependency directories 60 | node_modules/ 61 | jspm_packages/ 62 | 63 | # Snowpack dependency directory (https://snowpack.dev/) 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | *.tsbuildinfo 68 | 69 | # Optional npm cache directory 70 | .npm 71 | 72 | # Optional eslint cache 73 | .eslintcache 74 | 75 | # Microbundle cache 76 | .rpt2_cache/ 77 | .rts2_cache_cjs/ 78 | .rts2_cache_es/ 79 | .rts2_cache_umd/ 80 | 81 | # Optional REPL history 82 | .node_repl_history 83 | 84 | # Output of 'npm pack' 85 | *.tgz 86 | 87 | # Yarn Integrity file 88 | .yarn-integrity 89 | 90 | # dotenv environment variables file 91 | .env 92 | .env.test 93 | .env.production 94 | 95 | # parcel-bundler cache (https://parceljs.org/) 96 | .cache 97 | .parcel-cache 98 | 99 | # Next.js build output 100 | .next 101 | out 102 | 103 | # Nuxt.js build / generate output 104 | .nuxt 105 | dist 106 | 107 | # Gatsby files 108 | .cache/ 109 | # Comment in the public line in if your project uses Gatsby and not Next.js 110 | # https://nextjs.org/blog/next-9-1#public-directory-support 111 | # public 112 | 113 | # vuepress build output 114 | .vuepress/dist 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/reference/configuration.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration Reference 3 | description: An overview of all the configuration options Starlight supports. 4 | --- 5 | 6 | ## Configure the `icon` integration 7 | 8 | Astro Icon is an integration built on top the [Astro](https://astro.build) web framework. You can configure your project inside the `astro.config.mjs` configuration file: 9 | 10 | ```diff lang="js" title="astro.config.mjs" 11 | import { defineConfig } from 'astro/config'; 12 | + import icon from 'astro-icon'; 13 | 14 | export default defineConfig({ 15 | integrations: [ 16 | + icon({ /* options */ }) 17 | ] 18 | }); 19 | ``` 20 | 21 | You can pass the following options to the `icon` integration. 22 | 23 | ### `include` 24 | 25 | **type:** `Record` 26 | 27 | Filter the specific icons to include from `@iconify-json/*` sets in the final server bundle. 28 | 29 | ```js {7-12} 30 | import { defineConfig } from 'astro/config'; 31 | import icon from 'astro-icon'; 32 | 33 | export default defineConfig({ 34 | integrations: [ 35 | icon({ 36 | include: { 37 | // Include only three `mdi` icons in the bundle 38 | mdi: ['account', 'account-plus', 'account-minus'], 39 | // Include all `uis` icons 40 | uis: ['*'] 41 | } 42 | }) 43 | ] 44 | }); 45 | ``` 46 | 47 | :::caution 48 | By default, all icons from every installed set are included! 49 | 50 | When deploying an Astro site for server rendering, it is **highly** recommended to include _only_ the icons that are needed. 51 | ::: 52 | 53 | ### `iconDir` 54 | 55 | To use a local icon directory other than the default `src/icons/`, set the `iconDir` option. 56 | 57 | ```js {7} 58 | import { defineConfig } from "astro/config"; 59 | import icon from "astro-icon"; 60 | 61 | export default defineConfig({ 62 | integrations: [ 63 | icon({ 64 | iconDir: "src/assets/icons", 65 | }) 66 | ] 67 | }); 68 | ``` 69 | 70 | ### `svgoOptions` 71 | 72 | Control the behavior of local `.svg` optimization by customizing the [`svgo`](https://github.com/svg/svgo) options. 73 | 74 | Refer to the official [`svgo` configuration options](https://github.com/svg/svgo#configuration) for more information. 75 | 76 | ```js {7-24} 77 | import { defineConfig } from "astro/config"; 78 | import icon from "astro-icon"; 79 | 80 | export default defineConfig({ 81 | integrations: [ 82 | icon({ 83 | svgoOptions: { 84 | multipass: true, 85 | plugins: [ 86 | { 87 | name: "preset-default", 88 | params: { 89 | overrides: { 90 | // customize default plugin options 91 | inlineStyles: { 92 | onlyMatchedOnce: false, 93 | }, 94 | // or disable plugins 95 | removeDoctype: false, 96 | } 97 | } 98 | } 99 | ] 100 | } 101 | }) 102 | ] 103 | }); 104 | ``` 105 | -------------------------------------------------------------------------------- /packages/core/src/loaders/loadLocalCollection.ts: -------------------------------------------------------------------------------- 1 | import { 2 | cleanupSVG, 3 | importDirectory, 4 | isEmptyColor, 5 | parseColors, 6 | runSVGO, 7 | } from "@iconify/tools"; 8 | import type { IconCollection } from "../../typings/integration"; 9 | import type { SVG, Color, SVGOOptions } from "../../typings/iconify"; 10 | 11 | export default async function createLocalCollection( 12 | dir: string, 13 | options: SVGOOptions = { plugins: ["preset-default"] }, 14 | ): Promise { 15 | // Import icons 16 | const local = await importDirectory(dir, { 17 | prefix: "local", 18 | keepTitles: true, 19 | includeSubDirs: true, 20 | ignoreImportErrors: "warn", 21 | keyword: (file) => file.subdir + file.file, 22 | }); 23 | 24 | // Validate, clean up, fix palette and optimize 25 | await local.forEach(async (name, type) => { 26 | if (type !== "icon") { 27 | return; 28 | } 29 | 30 | // Get SVG instance for parsing 31 | const svg = local.toSVG(name); 32 | if (svg === null) { 33 | // Invalid icon 34 | local.remove(name); 35 | return; 36 | } 37 | 38 | // Clean up and optimize icons 39 | try { 40 | // Clean up icon code 41 | cleanupSVG(svg, { keepTitles: true }); 42 | 43 | // Validate if Icon is monotone 44 | if (await isMonochrome(svg)) { 45 | // If so, convert to use currentColor 46 | await convertToCurrentColor(svg); 47 | } 48 | 49 | // Optimize 50 | runSVGO(svg, options); 51 | } catch (err) { 52 | // Invalid icon 53 | console.error(`Error parsing ${name}:`, err); 54 | local.remove(name); 55 | return; 56 | } 57 | 58 | // Update icon 59 | local.fromSVG(name, svg); 60 | }); 61 | 62 | return local.export(true); 63 | } 64 | 65 | async function convertToCurrentColor(svg: SVG): Promise { 66 | await parseColors(svg, { 67 | defaultColor: "currentColor", 68 | callback: (_, colorStr, color) => { 69 | return color === null || isEmptyColor(color) || isWhite(color) 70 | ? colorStr 71 | : "currentColor"; 72 | }, 73 | }); 74 | } 75 | 76 | async function isMonochrome(svg: SVG): Promise { 77 | let monochrome = true; 78 | await parseColors(svg, { 79 | defaultColor: "currentColor", 80 | callback: (_, colorStr, color) => { 81 | if (!monochrome) return colorStr; 82 | monochrome = 83 | !color || isEmptyColor(color) || isWhite(color) || isBlack(color); 84 | return colorStr; 85 | }, 86 | }); 87 | 88 | return monochrome; 89 | } 90 | 91 | function isBlack(color: Color): boolean { 92 | switch (color.type) { 93 | case "rgb": 94 | return color.r === 0 && color.r === color.g && color.g === color.b; 95 | } 96 | return false; 97 | } 98 | 99 | function isWhite(color: Color): boolean { 100 | switch (color.type) { 101 | case "rgb": 102 | return color.r === 255 && color.r === color.g && color.g === color.b; 103 | } 104 | return false; 105 | } 106 | -------------------------------------------------------------------------------- /demo/src/icons/logos/deno.svg: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/guides/customization.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Customizing Icons 3 | description: Using icons with Astro Icon. 4 | prev: false 5 | --- 6 | 7 | import { Tabs, TabItem } from '@astrojs/starlight/components'; 8 | 9 | Astro Icon is designed to support custom icons that exist as `.svg` files in your project. 10 | It also supports any open source icon set distributed by [Iconify](https://iconify.design/). 11 | 12 | ## Local icons 13 | 14 | Add new icons to your site by creating `.svg` files in `/src/icons/`. 15 | Use sub-folders to organize your files and create multiple sets of icons. 16 | 17 | Icons in the `/src/icons/` directory can be automatically referenced by their slug, for example: 18 | 19 | ```astro mark="/src/icons/logo.svg" mark="logo" mark="/src/icons/logos/astro.svg" mark="logos/astro" 20 | --- 21 | import { Icon } from 'astro-icon/components' 22 | --- 23 | 24 | 25 | 26 | 27 | 28 | 29 | ``` 30 | 31 | Local `.svg` files are automatically optimized with [`svgo`](https://github.com/svg/svgo). Specific `svgo` options can be [configured in the integration](/reference/configuration). 32 | 33 | ## Open Source Icon Sets 34 | 35 | [Iconify](https://iconify.design/) is a project that distributes normalized packages of open source icon sets. 36 | After installing an icon set in your project, icons will be automatically available to the `Icon` component. 37 | 38 | ### Find an icon set 39 | 40 | Visit the official [Iconify Icon Sets](https://icon-sets.iconify.design/) explorer or the popular [Icônes](https://icones.js.org/) app to browse the available icon sets. 41 | 42 | ### Install dependency 43 | 44 | After identifying the icon set you would like to use, you must install the corresponding `@iconify-json/*` package. 45 | 46 | As an example, to install the [Material Design Icons](https://icones.js.org/collection/mdi) set, run the following command: 47 | 48 | 49 | 50 | 51 | ```sh 52 | npm install @iconify-json/mdi 53 | ``` 54 | 55 | 56 | 57 | 58 | ```sh 59 | pnpm add @iconify-json/mdi 60 | ``` 61 | 62 | 63 | 64 | 65 | ```sh 66 | yarn add @iconify-json/mdi 67 | ``` 68 | 69 | 70 | 71 | 72 | 73 | ### Using an icon set 74 | 75 | Installed icon sets can be automatically referenced by their prefixed id, for example: 76 | 77 | ```astro mark="@iconify-json/mdi" mark="mdi:account" 78 | --- 79 | import { Icon } from 'astro-icon/components' 80 | --- 81 | 82 | 83 | 84 | ``` 85 | 86 | ### Using multiple icon sources 87 | 88 | You are not limited to a single icon source! 89 | 90 | - You may mix and match local icons with an `@iconify-json/*` icon set. 91 | - You may install multiple `@iconify-json/*` icon sets. 92 | 93 | :::danger 94 | **If your Astro project uses the `server` or `hybrid` output**, be mindful that every icon that could _potentially_ be referenced will be included in your server's JavaScript bundle by default! 95 | 96 | Reference the [Deployment](/guides/deployment/) guide to understand how to optimize your final server bundle size. 97 | ::: 98 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/guides/components.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components 3 | description: Using the Icon component 4 | --- 5 | 6 | Astro Icon's main API is an `Icon` component that automatically inlines an `` directly in your markup. 7 | 8 | ## Icon 9 | 10 | You can use the `Icon` component by importing it from `astro-icon/components` and rendering it as a normal [Astro Component](https://docs.astro.build/en/core-concepts/astro-components/). 11 | 12 | ```astro mark="Icon" {6} 13 | --- 14 | import { Icon } from 'astro-icon/components' 15 | --- 16 | 17 | 18 | 19 | ``` 20 | 21 | Because `astro-icon` is powered by Astro, this component only renders on the server to static HTML. It has no runtime footprint. 22 | 23 | ### Props 24 | 25 | The `Icon` component accepts the following properties: 26 | 27 | ```ts 28 | interface Props extends HTMLAttributes<"svg"> { 29 | /** The name of the icon to include */ 30 | name: string; 31 | /** Shorthand for including a {props.title} element in the SVG */ 32 | title?: string; 33 | /** Shorthand for including a {props.desc} element in the SVG */ 34 | desc?: string; 35 | /** Shorthand for setting width and height */ 36 | size?: number | string; 37 | width?: number | string; 38 | height?: number | string; 39 | } 40 | ``` 41 | 42 | The `Icon` also accepts any global HTML attributes and `aria` attributes. They will be forwarded to the rendered `` element. 43 | 44 | ### Automatically optimized sprites 45 | 46 | Because Astro controls the entire rendering lifecycle for a given `Request`, `astro-icon` is able to automatically optimize repeated references to the same icon on a page. 47 | 48 | The approach uses a novel take on the more traditional [SVG Sprite](https://css-tricks.com/svg-sprites-use-better-icon-fonts/) system that leverages a single `` sprite for your entire site. The first time the `Icon` component is included on a page, it defines a sprite [``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol) with a unique ID and immediately renders that symbol with the [``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use) element. If the same icon is referenced again, `Icon` will render only a `` element, reducing the overall size of your HTML document by referencing the existing ``. 49 | 50 | ```astro 51 | --- 52 | import { Icon } from 'astro-icon/components' 53 | --- 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ``` 68 | 69 | ## Usage with Framework Components 70 | 71 | The `` component, like any other Astro component, cannot be used directly in [UI framework components](https://docs.astro.build/en/core-concepts/framework-components/). 72 | 73 | But, you can pass the static content generated by `` to a framework component inside a `.astro` file as children or using a [named ``](https://docs.astro.build/en/core-concepts/framework-components/#can-i-use-astro-components-inside-my-framework-components): 74 | 75 | ```astro 76 | --- 77 | import ReactComponent from './ReactComponent.jsx' 78 | import { Icon } from "astro-icon/components" 79 | --- 80 | 81 | 82 | 83 | 84 | ``` 85 | -------------------------------------------------------------------------------- /packages/core/src/loaders/loadIconifyCollections.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AstroIconCollectionMap, 3 | IconCollection, 4 | IntegrationOptions, 5 | } from "../../typings/integration"; 6 | import type { AutoInstall } from "../../typings/iconify"; 7 | 8 | import { readFile } from "node:fs/promises"; 9 | import { getIcons } from "@iconify/utils"; 10 | import { loadCollectionFromFS } from "@iconify/utils/lib/loader/fs"; 11 | import { promisify } from "node:util"; 12 | import { exec } from "node:child_process"; 13 | 14 | const execa = promisify(exec); 15 | 16 | interface LoadOptions { 17 | root: URL; 18 | include?: IntegrationOptions["include"]; 19 | } 20 | 21 | export default async function loadIconifyCollections({ 22 | root, 23 | include = {}, 24 | }: LoadOptions): Promise { 25 | const installedCollections = await detectInstalledCollections(root); 26 | // If icons are installed locally but not explicitly included, include the whole pack 27 | for (let name of installedCollections) { 28 | if (include[name] !== undefined) continue; 29 | include[name] = ["*"]; 30 | } 31 | const possibleCollections = await Promise.all( 32 | installedCollections.map((collectionName) => 33 | loadCollection(collectionName).then( 34 | (possibleCollection) => [collectionName, possibleCollection] as const, 35 | ), 36 | ), 37 | ); 38 | 39 | const collections = possibleCollections.reduce( 40 | (acc, [name, collection]) => { 41 | if (!collection) { 42 | console.error( 43 | `[astro-icon] "${name}" does not appear to be a valid iconify collection! Did you install the "@iconify-json/${name}" dependency?`, 44 | ); 45 | return acc; 46 | } 47 | 48 | const requestedIcons = Array.from(new Set(include[name])); 49 | 50 | // Requested entire icon collection 51 | if (requestedIcons.length === 1 && requestedIcons[0] === "*") { 52 | acc[name] = collection; 53 | return acc; 54 | } 55 | 56 | const reducedCollection = getIcons(collection, requestedIcons); 57 | if (!reducedCollection) { 58 | console.error( 59 | `[astro-icon] "${name}" failed to load the specified icons!`, 60 | ); 61 | return acc; 62 | } else if ( 63 | Object.keys(reducedCollection.icons).length !== requestedIcons.length 64 | ) { 65 | console.error( 66 | `[astro-icon] "${name}" failed to load at least one of the specified icons! Verify the icon names are included in the icon collection.`, 67 | ); 68 | } 69 | 70 | acc[name] = reducedCollection; 71 | return acc; 72 | }, 73 | {}, 74 | ); 75 | 76 | return collections; 77 | } 78 | 79 | export async function loadCollection( 80 | name: string, 81 | autoInstall?: AutoInstall, 82 | ): Promise { 83 | if (!name) return; 84 | 85 | return loadCollectionFromFS(name, autoInstall); 86 | } 87 | 88 | async function detectInstalledCollections(root: URL) { 89 | try { 90 | let packages: string[] = []; 91 | const text = await readFile(new URL("./package.json", root), { 92 | encoding: "utf8", 93 | }); 94 | const { dependencies = {}, devDependencies = {} } = JSON.parse(text); 95 | packages.push(...Object.keys(dependencies)); 96 | packages.push(...Object.keys(devDependencies)); 97 | const collections = packages 98 | .filter((name) => name.startsWith("@iconify-json/")) 99 | .map((name) => name.replace("@iconify-json/", "")); 100 | return collections; 101 | } catch {} 102 | return []; 103 | } 104 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/getting-started.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Started 3 | description: Learn how to add Astro Icon to your existing Astro project. 4 | next: 5 | link: /guides/customization/ 6 | label: Customizing Icons 7 | --- 8 | 9 | import { Tabs, TabItem } from '@astrojs/starlight/components'; 10 | 11 | Astro Icon is a straightforward icon system for the [Astro](https://astro.build) framework. 12 | This guide assumes that you have an existing Astro project. 13 | 14 | See [the Astro installation guide](https://docs.astro.build/en/install/auto/) if you are starting a brand new project. 15 | 16 | ## Installation 17 | 18 | ### Quick Install 19 | 20 | The `astro add` command-line tool automates the installation for you. Run one of the following commands in a new terminal window. (If you aren't sure which package manager you're using, run the first command.) Then, follow the prompts, and type "y" in the terminal (meaning "yes") for each one. 21 | 22 | 23 | 24 | 25 | ```sh 26 | npx astro add astro-icon 27 | ``` 28 | 29 | 30 | 31 | 32 | ```sh 33 | pnpm astro add astro-icon 34 | ``` 35 | 36 | 37 | 38 | 39 | ```sh 40 | yarn astro add astro-icon 41 | ``` 42 | 43 | 44 | 45 | 46 | 47 | If you run into any issues, [feel free to report them to us on GitHub](https://github.com/natemoo-re/astro-icon/issues) and try the manual installation steps below. 48 | 49 | ### Manual Install 50 | 51 | First, install the `astro-icon` package using your package manager. Run one of the following commands in the terminal: 52 | 53 | 54 | 55 | 56 | ```sh 57 | npm install astro-icon 58 | ``` 59 | 60 | 61 | 62 | 63 | ```sh 64 | pnpm add astro-icon 65 | ``` 66 | 67 | 68 | 69 | 70 | ```sh 71 | yarn add astro-icon 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | Then, apply this integration to your `astro.config.*` file using the `integrations` property: 79 | 80 | ```diff title="astro.config.mjs" lang="js" ins="icon()" 81 | import { defineConfig } from "astro/config"; 82 | + import icon from "astro-icon"; 83 | 84 | export default defineConfig({ 85 | integrations: [icon()], 86 | }); 87 | ``` 88 | 89 | ### Add Icons 90 | 91 | Add new icons to your site by creating `.svg` files in `/src/icons/`. 92 | Use sub-folders to organize your files and create multiple sets of icons. 93 | 94 | Icons in the `/src/icons/` directory can be automatically referenced by their slug, for example: 95 | 96 | ```astro mark="/src/icons/logo.svg" mark="logo" mark="/src/icons/logos/astro.svg" mark="logos/astro" 97 | --- 98 | import { Icon } from 'astro-icon/components' 99 | --- 100 | 101 | 102 | 103 | 104 | 105 | 106 | ``` 107 | 108 | 109 | ### Next steps 110 | 111 | - **Configure:** Learn about additional icon options in [“Customizing Icons”](/guides/customization/). 112 | - **Components:** Understand the built-in `Icon` component in the [“Components”](/guides/components/) guide. 113 | - **Deploy:** Before you publish your project, refer to the [“Deployment”](/guides/deployment/) guide. 114 | 115 | ## Updating Astro Icon 116 | 117 | Astro Icon is a third-party Astro integration, which are not yet supported by `@astrojs/upgrade`. Instead, you can upgrade `astro-icon` by running the following command in your terminal: 118 | 119 | 120 | 121 | 122 | ```sh 123 | npm install astro-icon@latest 124 | ``` 125 | 126 | 127 | 128 | 129 | ```sh 130 | pnpm add astro-icon@latest 131 | ``` 132 | 133 | 134 | 135 | 136 | ```sh 137 | yarn add astro-icon@latest 138 | ``` 139 | 140 | 141 | 142 | 143 | See the [Astro Icon changelog](https://github.com/natemoo-re/astro-icon/blob/main/packages/core/CHANGELOG.md) for a full list of the changes made in each release. 144 | 145 | ## Troubleshooting Astro Icon 146 | 147 | Use the [Customizing Icons](/guides/customization/) guide and [project configuration](/reference/configuration/) reference pages to ensure that Astro Icon is configured and functioning properly. 148 | See the guides in the sidebar for help with additional topics. 149 | 150 | If your answer cannot be found in these docs, please visit the [full Astro Docs](https://docs.astro.build) for complete Astro documentation. 151 | Your question may be answered by understanding how Astro works in general. 152 | 153 | You can also check for any known [Astro Icon issues on GitHub](https://github.com/natemoo-re/astro-icon/issues). Although this is not an official Astro package, we encourage you to join the [Astro Discord](https://astro.build/chat/) and chat with the active, friendly Astro community! 154 | -------------------------------------------------------------------------------- /packages/core/components/Icon.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // @ts-ignore virtual module 3 | import icons, { config } from "virtual:astro-icon"; 4 | // @ts-ignore generated by typegen 5 | import type { Icon } from "virtual:astro-icon"; 6 | import { getIconData, iconToSVG } from "@iconify/utils"; 7 | import type { HTMLAttributes } from "astro/types"; 8 | import { cache } from "./cache.js"; 9 | import type { IconifyIconBuildResult } from "@iconify/utils/lib/svg/build.js"; 10 | 11 | interface Props extends HTMLAttributes<"svg"> { 12 | name: Icon; 13 | "is:inline"?: boolean; 14 | title?: string; 15 | desc?: string; 16 | size?: number | string; 17 | width?: number | string; 18 | height?: number | string; 19 | } 20 | 21 | class AstroIconError extends Error { 22 | public hint: string = ''; 23 | 24 | constructor(message: string) { 25 | super(message); 26 | } 27 | } 28 | 29 | const req = Astro.request; 30 | const { name = "", title, desc, "is:inline": inline = false, ...props } = Astro.props; 31 | const map = cache.get(req) ?? new Map(); 32 | const i = map.get(name) ?? 0; 33 | map.set(name, i + 1); 34 | cache.set(req, map); 35 | 36 | const { include = {} } = config; 37 | const sets = Object.keys(include); 38 | 39 | const includeSymbol = !inline && i === 0; 40 | 41 | let [setName, iconName] = (name as string).split(":"); 42 | 43 | if (!setName && iconName) { 44 | const err = new AstroIconError(`Invalid "name" provided!`); 45 | if (import.meta.env.DEV) { 46 | err.hint = `The provided value of "${name}" is invalid.\n\nDid you forget the icon set name? If you were attemping to reference a local icon, use the icon's name directly. (ie. "${iconName}")`; 47 | } 48 | throw err; 49 | } 50 | 51 | // No iconName, assume local icon reference 52 | if (!iconName) { 53 | // Assign the provided setName to the iconName 54 | iconName = setName; 55 | setName = "local"; 56 | 57 | // Check if the local icon set exists 58 | if (!icons[setName]) { 59 | const err = new AstroIconError('Unable to load the "local" icon set!'); 60 | if (import.meta.env.DEV) { 61 | err.hint = 62 | 'It looks like the "local" set was not loaded.\n\nDid you forget to create the icon directory or to update your config?'; 63 | } 64 | throw err; 65 | } 66 | 67 | // Check if the icon is missing from the local collection 68 | if (!(iconName in icons[setName].icons)) { 69 | const err = new AstroIconError(`Unable to locate "${name}" icon!`); 70 | if (import.meta.env.DEV) { 71 | err.hint = `The icon named "${iconName}" was not found in your local icon directory.\n\nDid you forget to configure your icon directory or make a typo?`; 72 | } 73 | throw err; 74 | } 75 | } 76 | 77 | const collection = icons[setName]; 78 | 79 | // Iconify collection not configured correctly 80 | if (!collection) { 81 | const err = new AstroIconError(`Unable to locate the "${setName}" icon set!`); 82 | if (import.meta.env.DEV) { 83 | if (sets.includes(setName)) { 84 | err.hint = `It looks like the "${setName}" set was not loaded.\n\nDid you install the "@iconify-json/${setName}" dependency?`; 85 | } else { 86 | err.hint = `It looks like the "${setName}" set is not included in your configuration.\n\nDo you need to add the "${setName}" set?`; 87 | } 88 | } 89 | throw err; 90 | } 91 | 92 | const iconData = getIconData(collection, iconName ?? setName); 93 | // Missing icon from the icon collection 94 | if (!iconData) { 95 | const err = new AstroIconError(`Unable to locate "${name}" icon!`); 96 | if (import.meta.env.DEV) { 97 | const [maybeStar] = include[setName]; 98 | if (maybeStar === "*" || include[setName].includes(iconName)) { 99 | err.hint = `The "${setName}" set does not include an icon named "${iconName}".\n\nIs this a typo?`; 100 | } else { 101 | err.hint = `The "${setName}" set is not configured to include an icon named "${iconName}".\n\nDo you need to add it to your configuration?`; 102 | } 103 | } 104 | throw err; 105 | } 106 | 107 | const id = `ai:${collection.prefix}:${iconName ?? setName}`; 108 | 109 | if (props.size) { 110 | props.width = props.size; 111 | props.height = props.size; 112 | delete props.size; 113 | } 114 | const renderData = iconToSVG(iconData); 115 | const normalizedProps = { ...renderData.attributes as Partial, ...props }; 116 | const normalizedBody = renderData.body; 117 | 118 | const { viewBox } = normalizedProps; 119 | if (includeSymbol) { 120 | delete normalizedProps.viewBox; 121 | } 122 | --- 123 | 124 | 125 | {title && {title}} 126 | {desc && {desc}} 127 | { 128 | inline ? ( 129 | 130 | ) : ( 131 | 132 | {includeSymbol && } 133 | 134 | 135 | ) 136 | } 137 | 138 | -------------------------------------------------------------------------------- /demo/src/icons/logos/alpine.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/core/src/vite-plugin-astro-icon.ts: -------------------------------------------------------------------------------- 1 | import type { AstroConfig, AstroIntegrationLogger } from "astro"; 2 | import { createHash } from "node:crypto"; 3 | import { parse, resolve } from "node:path"; 4 | import { mkdir, readFile, writeFile } from "node:fs/promises"; 5 | import type { Plugin } from "vite"; 6 | import type { 7 | AstroIconCollectionMap, 8 | IconCollection, 9 | IntegrationOptions, 10 | } from "../typings/integration"; 11 | import loadLocalCollection from "./loaders/loadLocalCollection.js"; 12 | import loadIconifyCollections from "./loaders/loadIconifyCollections.js"; 13 | 14 | interface PluginContext extends Pick { 15 | logger: AstroIntegrationLogger; 16 | } 17 | 18 | export function createPlugin( 19 | { include = {}, iconDir = "src/icons", svgoOptions }: IntegrationOptions, 20 | ctx: PluginContext, 21 | ): Plugin { 22 | let collections: AstroIconCollectionMap | undefined; 23 | const { root } = ctx; 24 | const virtualModuleId = "virtual:astro-icon"; 25 | const resolvedVirtualModuleId = "\0" + virtualModuleId; 26 | 27 | return { 28 | name: "astro-icon", 29 | resolveId(id) { 30 | if (id === virtualModuleId) { 31 | return resolvedVirtualModuleId; 32 | } 33 | }, 34 | 35 | async load(id) { 36 | if (id === resolvedVirtualModuleId) { 37 | try { 38 | if (!collections) { 39 | collections = await loadIconifyCollections({ root, include }); 40 | } 41 | const local = await loadLocalCollection(iconDir, svgoOptions); 42 | collections["local"] = local; 43 | logCollections(collections, { ...ctx, iconDir }); 44 | await generateIconTypeDefinitions(Object.values(collections), root); 45 | } catch (ex) { 46 | // Failed to load the local collection 47 | } 48 | return `export default ${JSON.stringify(collections)};\nexport const config = ${JSON.stringify({ include })}`; 49 | } 50 | }, 51 | configureServer({ watcher, moduleGraph }) { 52 | watcher.add(`${iconDir}/**/*.svg`); 53 | watcher.on("all", async (_, filepath: string) => { 54 | const parsedPath = parse(filepath); 55 | const resolvedIconDir = resolve(root.pathname, iconDir); 56 | const isSvgFileInIconDir = 57 | parsedPath.dir.startsWith(resolvedIconDir) && 58 | parsedPath.ext === ".svg"; 59 | const isAstroConfig = parsedPath.name === "astro.config"; 60 | if (!isSvgFileInIconDir && !isAstroConfig) return; 61 | console.log(`Local icons changed, reloading`); 62 | try { 63 | if (!collections) { 64 | collections = await loadIconifyCollections({ root, include }); 65 | } 66 | const local = await loadLocalCollection(iconDir, svgoOptions); 67 | collections["local"] = local; 68 | logCollections(collections, { ...ctx, iconDir }); 69 | await generateIconTypeDefinitions(Object.values(collections), root); 70 | moduleGraph.invalidateAll(); 71 | } catch (ex) { 72 | // Failed to load the local collection 73 | } 74 | return `export default ${JSON.stringify(collections)};\nexport const config = ${JSON.stringify({ include })}`; 75 | }); 76 | }, 77 | }; 78 | } 79 | 80 | function logCollections( 81 | collections: AstroIconCollectionMap, 82 | { logger, iconDir }: PluginContext & { iconDir: string }, 83 | ) { 84 | if (Object.keys(collections).length === 0) { 85 | logger.warn("No icons detected!"); 86 | return; 87 | } 88 | const names: string[] = Object.keys(collections).filter((v) => v !== "local"); 89 | if (collections["local"]) { 90 | names.unshift(iconDir); 91 | } 92 | logger.info(`Loaded icons from ${names.join(", ")}`); 93 | } 94 | 95 | async function generateIconTypeDefinitions( 96 | collections: IconCollection[], 97 | rootDir: URL, 98 | defaultPack = "local", 99 | ): Promise { 100 | const typeFile = new URL("./.astro/icon.d.ts", rootDir); 101 | await ensureDir(new URL("./", typeFile)); 102 | const oldHash = await tryGetHash(typeFile); 103 | const currentHash = collectionsHash(collections); 104 | if (currentHash === oldHash) { 105 | return; 106 | } 107 | await writeFile( 108 | typeFile, 109 | `// Automatically generated by astro-icon 110 | // ${currentHash} 111 | 112 | declare module 'virtual:astro-icon' { 113 | \texport type Icon = ${ 114 | collections.length > 0 115 | ? collections 116 | .map((collection) => 117 | Object.keys(collection.icons) 118 | .concat(Object.keys(collection.aliases ?? {})) 119 | .map( 120 | (icon) => 121 | `\n\t\t| "${ 122 | collection.prefix === defaultPack 123 | ? "" 124 | : `${collection.prefix}:` 125 | }${icon}"`, 126 | ), 127 | ) 128 | .flat(1) 129 | .join("") 130 | : "never" 131 | }; 132 | }`, 133 | ); 134 | } 135 | 136 | function collectionsHash(collections: IconCollection[]): string { 137 | const hash = createHash("sha256"); 138 | for (const collection of collections) { 139 | hash.update(collection.prefix); 140 | hash.update( 141 | Object.keys(collection.icons) 142 | .concat(Object.keys(collection.aliases ?? {})) 143 | .sort() 144 | .join(","), 145 | ); 146 | } 147 | return hash.digest("hex"); 148 | } 149 | 150 | async function tryGetHash(path: URL): Promise { 151 | try { 152 | const text = await readFile(path, { encoding: "utf-8" }); 153 | return text.split("\n", 3)[1].replace("// ", ""); 154 | } catch {} 155 | } 156 | 157 | async function ensureDir(path: URL): Promise { 158 | try { 159 | await mkdir(path, { recursive: true }); 160 | } catch {} 161 | } 162 | -------------------------------------------------------------------------------- /packages/www/src/content/docs/guides/upgrade/v1.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Upgrade to Astro Icon v1 3 | prev: false 4 | next: false 5 | --- 6 | 7 | import { Tabs, TabItem } from '@astrojs/starlight/components'; 8 | 9 | This guide will help you migrate from older versions of `astro-icon` to `astro-icon` v1. 10 | 11 | There are multiple breaking changes in `astro-icon` v1 that require changes to your existing code. This guide will outline the steps you must take. 12 | 13 | ### History 14 | 15 | The original version of `astro-icon` was built in December 2021, when Astro had not even released a stable v1. Every Astro project was, by definition, a static site. Server-side rendering was not a supported feature and there was no official API for integrations. `astro-icon`'s architecture reflected the reduced scope that Astro had at the time. 16 | 17 | In v1, `astro-icon` has been refactored to provide a more stable foundation that supports everything Astro v3+ is capable of, including server-side rendering. 18 | 19 | ## Upgrade `astro-icon` 20 | 21 | Update your project’s version of `astro-icon` to the latest version using your package manager. 22 | 23 | 24 | 25 | 26 | ```sh ins="latest" 27 | npm install astro-icon@latest 28 | ``` 29 | 30 | 31 | 32 | 33 | ```sh ins="latest" 34 | pnpm add astro-icon@latest 35 | ``` 36 | 37 | 38 | 39 | 40 | ```sh ins="latest" 41 | yarn add astro-icon@latest 42 | ``` 43 | 44 | 45 | 46 | 47 | 48 | ## Breaking Changes 49 | 50 | ### Changed: `astro-icon` is now an integration 51 | 52 | In v0, the entire API surface was limited to the `Icon` and `Sprite` components. 53 | 54 | In v1, `astro-icon` has become a full-fledged integration. 55 | 56 | #### What should I do? 57 | 58 | Update your `astro.config.mjs` file to include the new `astro-icon` integration. 59 | 60 | ```js title="astro.config.mjs" ins="import icon from \"astro-icon\";" ins="icon()" 61 | import { defineConfig } from "astro/config"; 62 | import icon from "astro-icon"; 63 | 64 | export default defineConfig({ 65 | integrations: [icon()], 66 | }); 67 | ``` 68 | 69 | ### Removed: Remote API service 70 | 71 | In v0, icons were automatically fetched from a custom Astro Icon API, powered internally by [Iconify](https://iconify.design/). While this was convenient, missing icons and network latency caused frequent problems. 72 | 73 | In v1, icon sets **must** be installed as a dependency in your project. 74 | 75 | #### What should I do? 76 | 77 | Determine the icon sets (previously referred to as a "pack") used in your project. Install the equivalent `@iconify-json/` package. 78 | 79 | For example, if using the `mdi:account` and `carbon:basketball` icons, the `mdi` and `carbon` icons must be installed in your project. 80 | 81 | 82 | 83 | 84 | 85 | ```sh mark="mdi" mark="carbon" 86 | npm install @iconify-json/mdi @iconify-json/carbon 87 | ``` 88 | 89 | 90 | 91 | 92 | ```sh mark="mdi" mark="carbon" 93 | pnpm add @iconify-json/mdi @iconify-json/carbon 94 | ``` 95 | 96 | 97 | 98 | 99 | ```sh mark="mdi" mark="carbon" 100 | yarn add @iconify-json/mdi @iconify-json/carbon 101 | ``` 102 | 103 | 104 | 105 | 106 | 107 | ### Changed: component export location 108 | 109 | In v0, components were exported directly from the `astro-icon` package. 110 | 111 | In v1, components are exported from the `astro-icon/components` path. 112 | 113 | #### What should I do? 114 | 115 | Update your import statements to reference `astro-icon/components`. 116 | 117 | ```js ins="/components" 118 | import { Icon } from 'astro-icon/components' 119 | ``` 120 | 121 | ### Changed: styling attribute 122 | 123 | In v0, icons used an `astro-icon` attribute for styling. This was technically invalid HTML. 124 | 125 | In v1, icons use the `data-icon` attribute instead. 126 | 127 | #### What should I do? 128 | 129 | Replace any `[astro-icon]` selectors in your styles with the equivalent `[data-icon]` selector. 130 | 131 | ```diff lang="html" del="astro" ins="data" 132 | 142 | ``` 143 | 144 | ### Removed: `pack` prop 145 | 146 | In v0, the `Icon` component accepted separate `pack` and `name` props plus a shorthand `pack:name` syntax. 147 | 148 | In v1, the `Icon` component only accepts a `name` prop. Packs are always referenced via the shorthand `pack:name` syntax. 149 | 150 | #### What should I do? 151 | 152 | Update your components to replace the `pack` prop with the `name` prop. 153 | 154 | ```astro del="pack=\"mdi\"" ins="mdi:" 155 | 156 | ``` 157 | 158 | ### Removed: `Sprite` component 159 | 160 | In v0, the `Sprite` component was used to generate an SVG spritesheet. This required your entire page to be wrapped in a ``. 161 | 162 | In v1, the `Sprite` component has been removed. The `Icon` component now automatically optimizes itself into an SVG spritesheet when used multiple times on the same page. 163 | 164 | #### What should I do? 165 | 166 | Remove the `` wrapper from your pages. Replace any references to the `Sprite` component with the `Icon` component. 167 | 168 | ```diff lang="astro" del="Sprite," ins="Icon" ins="/components" 169 | --- 170 | import { Sprite, Icon } from 'astro-icon/components' 171 | --- 172 | 173 | - 174 | 175 | 176 | 177 | - 178 | + 179 | 180 | - 181 | ``` 182 | 183 | ### Removed: `createIconPack` utilities 184 | 185 | In v0, the `astro-icon/pack` module exported a `createIconPack` utility to create custom local icon packs from JS/TS files. 186 | 187 | In v1, the `astro-icon/pack` module has been removed. Network and custom loaders are no longer supported. All icons must be placed in the `src/icons/` directory. 188 | 189 | #### What should I do? 190 | 191 | Remove any loaders that used `createIconPack`. Instead, create a new directory for each icon pack in the `src/icons/` directory and add one `.svg` file for each icon. 192 | 193 | ### Removed: `optimize` prop 194 | 195 | In v0, the `Icon` component accepted an `optimize` prop, but it defaulted to `true`. This controlled the SVGO optimizations for specific icons. 196 | 197 | In v1, the `optimize` prop has been removed. SVGO optimizations are automatically performed during the build rather than dynamically at runtime. 198 | 199 | #### What should I do? 200 | 201 | Remove any usage of the `optimize` prop. Configure SVGO optimization by passing `svgoOptions` to the `icon()` integration instead. 202 | 203 | ```astro del="optimize" 204 | 205 | ``` 206 | 207 | ```js title="astro.config.mjs" {7-15} 208 | import { defineConfig } from "astro/config"; 209 | import icon from "astro-icon"; 210 | 211 | export default defineConfig({ 212 | integrations: [ 213 | icon({ 214 | svgoOptions: { 215 | plugins: [ 216 | "preset-default", 217 | { 218 | name: "convertColors", 219 | params: { currentColor: true }, 220 | }, 221 | ], 222 | }, 223 | }), 224 | ], 225 | }); 226 | ``` 227 | -------------------------------------------------------------------------------- /demo/src/icons/logos/alpine-multi-color.svg: -------------------------------------------------------------------------------- 1 | 2 | Custom Preset 4 Copy 5 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # Astro Icon 2 | 3 | This **[Astro integration](https://docs.astro.build/en/guides/integrations-guide/)** provides a straight-forward `Icon` component for [Astro](https://astro.build). 4 | 5 | - [Why Astro Icon](#why-astro-icon) 6 | - [Installation](#installation) 7 | - [Usage](#usage) 8 | - [Configuration](#configuration) 9 | - [Examples](#examples) 10 | - [Migrating to v1](#migrating-to-v1) 11 | - [Contributing](#contributing) 12 | - [Changelog](#changelog) 13 | 14 | ## Why Astro Icon 15 | 16 | ## Installation 17 | 18 | ### Quick Install 19 | 20 | The `astro add` command-line tool automates the installation for you. Run one of the following commands in a new terminal window. (If you aren't sure which package manager you're using, run the first command.) Then, follow the prompts, and type "y" in the terminal (meaning "yes") for each one. 21 | 22 | ```sh 23 | # Using NPM 24 | npx astro add astro-icon 25 | # Using Yarn 26 | yarn astro add astro-icon 27 | # Using PNPM 28 | pnpm astro add astro-icon 29 | ``` 30 | 31 | If you run into any issues, [feel free to report them to us on GitHub](https://github.com/natemoo-re/astro-icon/issues) and try the manual installation steps below. 32 | 33 | ### Manual Install 34 | 35 | First, install the `astro-icon` package using your package manager. If you're using npm or aren't sure, run this in the terminal: 36 | 37 | ```sh 38 | npm install astro-icon 39 | ``` 40 | 41 | Then, apply this integration to your `astro.config.*` file using the `integrations` property: 42 | 43 | **`astro.config.mjs`** 44 | 45 | ```js 46 | import { defineConfig } from "astro/config"; 47 | import icon from "astro-icon"; 48 | 49 | export default defineConfig({ 50 | integrations: [icon()], 51 | }); 52 | ``` 53 | 54 | ## Usage 55 | 56 | Astro Icon is ready to use, with zero additional configuration. The included `Icon` component allows you to inline `svg`s directly into your HTML. Repeasted 57 | 58 | ### Local Icons 59 | 60 | By default, Astro Icon supports custom local `svg` icons. They are optimized with [`svgo`](https://github.com/svg/svgo) automatically with no extra build step. See ["A Pretty Good SVG Icon System"](https://css-tricks.com/pretty-good-svg-icon-system/#just-include-the-icons-inline) from CSS Tricks. 61 | 62 | 1. Create a directory inside of `src/` named `icons/`. 63 | 2. Add each desired icon as an individual `.svg` file to `src/icons/` 64 | 3. Reference a specific icon file using the `name` prop. 65 | 66 | ```astro 67 | --- 68 | import { Icon } from 'astro-icon/components'; 69 | --- 70 | 71 | 72 | 73 | ``` 74 | 75 | ## Iconify Icons 76 | 77 | Astro Icon also supports [Iconify](https://iconify.design) icon sets out-of-the-box. 78 | 79 | 1. Find an Icon Set to use on the [Iconify Icon Sets website](https://icon-sets.iconify.design/) 80 | 2. Install the package (eg. `npm i -D @iconify-json/mdi`) 81 | 3. Reference a specific icon using the `name` prop with (eg. `mdi:account`) 82 | 83 | ```astro 84 | --- 85 | import { Icon } from 'astro-icon/components' 86 | --- 87 | 88 | 89 | 90 | ``` 91 | 92 | ### Props 93 | 94 | The `Icon` component allows these custom properties: 95 | 96 | ```ts 97 | interface Props extends HTMLAttributes<"svg"> { 98 | /** 99 | * References a specific Icon 100 | */ 101 | name: string; 102 | "is:inline"?: boolean; 103 | title?: string; 104 | desc?: string; 105 | size?: number | string; 106 | width?: number | string; 107 | height?: number | string; 108 | } 109 | ``` 110 | 111 | The `Icon` also accepts any global HTML attributes and `aria` attributes. They will be forwarded to the rendered `` element. 112 | See the [`Props.ts`](./packages/core/components/Icon.astro#L10-L17) file for more details. 113 | 114 | ### Styling 115 | 116 | Styling your icons is straightforward. Any styles can be targeted to the `[data-icon]` attribute selector. If you want to target a specific icon, you may target it by name using `[data-icon="filename"]`. 117 | 118 | ```astro 119 | --- 120 | import { Icon } from 'astro-icon/components'; 121 | --- 122 | 123 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | ``` 142 | 143 | ### Using with Frameworks 144 | 145 | Astro Icon can be used with other frameworks utilizing the [`slot` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot). You can read more about how to use Slots in Astro here. [Passing Children to Framework Components](https://docs.astro.build/en/core-concepts/framework-components/#passing-children-to-framework-components) 146 | 147 | ## Configuration 148 | 149 | ### Configuring the Integration 150 | 151 | The Astro Icon integration has its own options for controlling the `Icon` component. Change these in the `astro.config.mjs` file which is where your project's integration settings live. 152 | 153 | #### config.include 154 | 155 | For users with a project using `output: 'server'` or `output: 'hybrid'`, it is highly recommended to configure the exact icons that should be included in the server bundle. By default, every icon in the set will be bundled into the server JavaScript. 156 | 157 | To filter the exact Iconify icons that should be included, set an array of allowed icons inside of the `include` object. Only these icons will be bundled. 158 | 159 | **`astro.config.mjs`** 160 | 161 | ```js 162 | import { defineConfig } from "astro/config"; 163 | import icon from "astro-icon"; 164 | 165 | export default defineConfig({ 166 | // ... 167 | integrations: [ 168 | icon({ 169 | include: { 170 | mdi: ["*"], // (Default) Loads entire Material Design Icon set 171 | mdi: ["account"], // Loads only Material Design Icon's "account" SVG 172 | }, 173 | }), 174 | ], 175 | }); 176 | ``` 177 | 178 | #### config.iconDir 179 | 180 | If you want to use a different custom svg icon directory instead of the default `src/icons/`, specify that file path using `config.iconDir` 181 | 182 | ```js ins={2} 183 | import { defineConfig } from "astro/config"; 184 | import icon from "astro-icon"; 185 | 186 | export default defineConfig({ 187 | // ... 188 | integrations: [ 189 | icon({ 190 | iconDir: "src/assets/icons", 191 | }), 192 | ], 193 | }); 194 | ``` 195 | 196 | #### config.svgoOptions 197 | 198 | If you want to behavior of `.svg` optimization, you can configure the `svgo` options rather than using the defaults. Read more about the available [`svgo` options here](https://github.com/svg/svgo#configuration). 199 | 200 | ```js 201 | import { defineConfig } from "astro/config"; 202 | import icon from "astro-icon"; 203 | 204 | export default defineConfig({ 205 | // ... 206 | integrations: [ 207 | icon({ 208 | svgoOptions: { 209 | multipass: true, 210 | plugins: [ 211 | { 212 | name: "preset-default", 213 | params: { 214 | overrides: { 215 | // customize default plugin options 216 | inlineStyles: { 217 | onlyMatchedOnce: false, 218 | }, 219 | 220 | // or disable plugins 221 | removeDoctype: false, 222 | }, 223 | }, 224 | }, 225 | ], 226 | }, 227 | }), 228 | ], 229 | }); 230 | ``` 231 | 232 | ## Migrating to v1 233 | 234 | `astro-icon` v1 contains a number of breaking changes. Please reference the [**Migrate to `astro-icon` v1** guide](https://www.astroicon.dev/guides/upgrade/v1/) to update from older versions of `astro-icon`. 235 | 236 | ## Contributing 237 | 238 | You're welcome to submit an issue or PR! 239 | 240 | ## Changelog 241 | 242 | See [CHANGELOG.md](CHANGELOG.md) for a history of changes to this integration. 243 | -------------------------------------------------------------------------------- /packages/core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # astro-icon 2 | 3 | ## 1.1.5 4 | 5 | ### Patch Changes 6 | 7 | - [#258](https://github.com/natemoo-re/astro-icon/pull/258) [`61d5da607914212b8c7895cbffb049512a289b5a`](https://github.com/natemoo-re/astro-icon/commit/61d5da607914212b8c7895cbffb049512a289b5a) Thanks [@maxchang3](https://github.com/maxchang3)! - Fix icon reloading logic to only trigger for relevant file changes 8 | 9 | ## 1.1.4 10 | 11 | ### Patch Changes 12 | 13 | - [#250](https://github.com/natemoo-re/astro-icon/pull/250) [`41218facd06f51a63d75cccb80c3745c256ec99f`](https://github.com/natemoo-re/astro-icon/commit/41218facd06f51a63d75cccb80c3745c256ec99f) Thanks [@harukats](https://github.com/harukats)! - Fixes type definitions and hash calculation for aliased icon names 14 | 15 | ## 1.1.3 16 | 17 | ### Patch Changes 18 | 19 | - [`1e6d429829a0e90ea2d43354daddedf026e08e51`](https://github.com/natemoo-re/astro-icon/commit/1e6d429829a0e90ea2d43354daddedf026e08e51) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes change detection logic for local icons while `astro dev` is running 20 | 21 | ## 1.1.2 22 | 23 | ### Patch Changes 24 | 25 | - [#247](https://github.com/natemoo-re/astro-icon/pull/247) [`fce07f17fe67116165d5d3dd279519bb7bbed55c`](https://github.com/natemoo-re/astro-icon/commit/fce07f17fe67116165d5d3dd279519bb7bbed55c) Thanks [@christina-de-martinez](https://github.com/christina-de-martinez)! - Adds a `desc` prop shorthand which maps to the SVG `` tag, similar to `title`. 26 | 27 | - [#246](https://github.com/natemoo-re/astro-icon/pull/246) [`4c5da3378436c2bee6ccdf4ad9cf0e1f32fb6903`](https://github.com/natemoo-re/astro-icon/commit/4c5da3378436c2bee6ccdf4ad9cf0e1f32fb6903) Thanks [@stramel](https://github.com/stramel)! - Fixes an issue where `viewBox` was not correctly passed to `` elements 28 | 29 | - [#245](https://github.com/natemoo-re/astro-icon/pull/245) [`ff3a66a8a357375076022b6f9800561ed845c071`](https://github.com/natemoo-re/astro-icon/commit/ff3a66a8a357375076022b6f9800561ed845c071) Thanks [@stramel](https://github.com/stramel)! - Fixes handling of duplicate icon entries in the integration configuration 30 | 31 | - [#243](https://github.com/natemoo-re/astro-icon/pull/243) [`a8c0a6c5fe2a01841c258af5fb3abe04839df5eb`](https://github.com/natemoo-re/astro-icon/commit/a8c0a6c5fe2a01841c258af5fb3abe04839df5eb) Thanks [@stramel](https://github.com/stramel)! - Replaces deprecated `xlink:href` attribute with standard `href` attribute 32 | 33 | ## 1.1.1 34 | 35 | ### Patch Changes 36 | 37 | - [#219](https://github.com/natemoo-re/astro-icon/pull/219) [`f18661fc47da152e7555d24b23143f0b481c852b`](https://github.com/natemoo-re/astro-icon/commit/f18661fc47da152e7555d24b23143f0b481c852b) Thanks [@Harry-Ross](https://github.com/Harry-Ross)! - Added better typings for height, width and size to accept non-number values (i.e. 2 rem) 38 | 39 | - [#203](https://github.com/natemoo-re/astro-icon/pull/203) [`a4ff8736965214e16ce0b72364f43b3a4973f281`](https://github.com/natemoo-re/astro-icon/commit/a4ff8736965214e16ce0b72364f43b3a4973f281) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes an issue where collections would not be updated when the dev server was automatically restarted 40 | 41 | - [#230](https://github.com/natemoo-re/astro-icon/pull/230) [`7b11f6b0fb8977bfa35305f48ce70e9bc04ea07a`](https://github.com/natemoo-re/astro-icon/commit/7b11f6b0fb8977bfa35305f48ce70e9bc04ea07a) Thanks [@frankievalentine](https://github.com/frankievalentine)! - Fixes a type definition issue caused by outdated dependency 42 | 43 | ## 1.1.0 44 | 45 | ### Minor Changes 46 | 47 | - [#200](https://github.com/natemoo-re/astro-icon/pull/200) [`d7528f61484d5b60108cbe00bc5fb856766688d0`](https://github.com/natemoo-re/astro-icon/commit/d7528f61484d5b60108cbe00bc5fb856766688d0) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Adds support for the `is:inline` directive, which bypasses automatic sprite optimization and directly embeds the plain SVG. 48 | 49 | ## 1.0.4 50 | 51 | ### Patch Changes 52 | 53 | - [#198](https://github.com/natemoo-re/astro-icon/pull/198) [`aac1ca330f6fdb56a6f3c32c4a91444ee746b557`](https://github.com/natemoo-re/astro-icon/commit/aac1ca330f6fdb56a6f3c32c4a91444ee746b557) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes a regression in `1.0.3` that changed how icons were sized 54 | 55 | ## 1.0.3 56 | 57 | ### Patch Changes 58 | 59 | - [`2aad9d7ab21cdeff91ce43a21babf70e81b1d116`](https://github.com/natemoo-re/astro-icon/commit/2aad9d7ab21cdeff91ce43a21babf70e81b1d116) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes an internal TypeScript issue that may have been visible when running `astro check` 60 | 61 | ## 1.0.2 62 | 63 | ### Patch Changes 64 | 65 | - [#184](https://github.com/natemoo-re/astro-icon/pull/184) [`beefcb732c266bc3eedfa12740c0842fef7deccf`](https://github.com/natemoo-re/astro-icon/commit/beefcb732c266bc3eedfa12740c0842fef7deccf) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improves handling of invalid local icons, which previously caused all local icons to silently fail. 66 | 67 | - [#179](https://github.com/natemoo-re/astro-icon/pull/179) [`b55cd5f92da8988467e86cb2a45d3dfa82ef3ffa`](https://github.com/natemoo-re/astro-icon/commit/b55cd5f92da8988467e86cb2a45d3dfa82ef3ffa) Thanks [@natemoo-re](https://github.com/natemoo-re)! - **BREAKING**: Requires subdirectory prefixes for local icons. 68 | 69 | This fixes a regression introduced in v1 and matches the previous v0 `name` behavior. 70 | 71 | As an example, the `src/icons/logos/astro.svg` file could previously be referenced by the name `astro`. It should correctly be referenced as `logos/astro`. 72 | 73 | **Before** 74 | 75 | ```jsx 76 | 77 | ``` 78 | 79 | **After** 80 | 81 | ```jsx 82 | 83 | ``` 84 | 85 | - [#180](https://github.com/natemoo-re/astro-icon/pull/180) [`580b5cd93d373ba72418365a97dac4cddf82afd7`](https://github.com/natemoo-re/astro-icon/commit/580b5cd93d373ba72418365a97dac4cddf82afd7) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Removes an unecessary warning when only using local icons 86 | 87 | ## 1.0.1 88 | 89 | ### Patch Changes 90 | 91 | - [#172](https://github.com/natemoo-re/astro-icon/pull/172) [`3819bd149236e7496beff275adc0239b098fe8ea`](https://github.com/natemoo-re/astro-icon/commit/3819bd149236e7496beff275adc0239b098fe8ea) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix broken link in README 92 | 93 | - [#175](https://github.com/natemoo-re/astro-icon/pull/175) [`c8c3df3c7fbeb85ad6bf5af67c53048ea26abefc`](https://github.com/natemoo-re/astro-icon/commit/c8c3df3c7fbeb85ad6bf5af67c53048ea26abefc) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes an issue that caused installed `@iconify-json/*` packages to not be detected in production environments 94 | 95 | ## 1.0.0 96 | 97 | ### Major Changes 98 | 99 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`a40531cddfe8e688d35bd25ae15ebc64a0a14ec1`](https://github.com/natemoo-re/astro-icon/commit/a40531cddfe8e688d35bd25ae15ebc64a0a14ec1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Finally, `astro-icon@1.0.0` has arrived! This release provides a more flexible and reliable method of icon management, removes a number of redundant APIs, and now relies on Astro's official integration API. 100 | 101 | Please see the [Upgade to `astro-icon` v1](https://astroicon.dev/guides/upgrade/v1/) guide for specific migration steps and [the brand new docs site](https://astroicon.dev) for more information. 102 | 103 | ### Patch Changes 104 | 105 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`a40531cddfe8e688d35bd25ae15ebc64a0a14ec1`](https://github.com/natemoo-re/astro-icon/commit/a40531cddfe8e688d35bd25ae15ebc64a0a14ec1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Updates the `exports` field to point to the correct `astro-icon/components` source file 106 | 107 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`a40531cddfe8e688d35bd25ae15ebc64a0a14ec1`](https://github.com/natemoo-re/astro-icon/commit/a40531cddfe8e688d35bd25ae15ebc64a0a14ec1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Moves warning about local directory to the moment they are used 108 | 109 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`a40531cddfe8e688d35bd25ae15ebc64a0a14ec1`](https://github.com/natemoo-re/astro-icon/commit/a40531cddfe8e688d35bd25ae15ebc64a0a14ec1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Makes the `astro-icon` integration's `include` settings optional. By default, all icons for any detected `@iconify-json/*` dependencies will be included. This makes migration much easier for existing static site users, while offering the same amount of control for server rendered users. 110 | 111 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`a40531cddfe8e688d35bd25ae15ebc64a0a14ec1`](https://github.com/natemoo-re/astro-icon/commit/a40531cddfe8e688d35bd25ae15ebc64a0a14ec1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Updates the SVGO options so that they are correctly passed through the build process 112 | 113 | ## 1.0.0-next.4 114 | 115 | ### Patch Changes 116 | 117 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`1d65511c418b0fef0668e760c33bff21deeb8ef3`](https://github.com/natemoo-re/astro-icon/commit/1d65511c418b0fef0668e760c33bff21deeb8ef3) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Updates the `exports` field to point to the correct `astro-icon/components` source file 118 | 119 | ## 1.0.0-next.3 120 | 121 | ### Patch Changes 122 | 123 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`ad93cfc54abe169f4a52b803eded540b94299dbc`](https://github.com/natemoo-re/astro-icon/commit/ad93cfc54abe169f4a52b803eded540b94299dbc) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Makes the `astro-icon` integration's `include` settings optional. By default, all icons for any detected `@iconify-json/*` dependencies will be included. This makes migration much easier for existing static site users, while offering the same amount of control for server rendered users. 124 | 125 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`ee99e2119b3bcc9b05376909a46a65da0087305b`](https://github.com/natemoo-re/astro-icon/commit/ee99e2119b3bcc9b05376909a46a65da0087305b) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Updates the SVGO options so that they are correctly passed through the build process 126 | 127 | ## 1.0.0-next.2 128 | 129 | ### Patch Changes 130 | 131 | - [#123](https://github.com/natemoo-re/astro-icon/pull/123) [`41554ad`](https://github.com/natemoo-re/astro-icon/commit/41554adcfff0aa80486d9f456d3b1c5fc66ca199) Thanks [@stramel](https://github.com/stramel)! - move warning about local directory to on use 132 | 133 | ## 1.0.0-next.1 134 | 135 | ### Patch Changes 136 | 137 | - Oops, actually publish `dist` 138 | 139 | ## 1.0.0-next.0 140 | 141 | ### Major Changes 142 | 143 | - [#111](https://github.com/natemoo-re/astro-icon/pull/111) [`f1c763d`](https://github.com/natemoo-re/astro-icon/commit/f1c763d506584aa551051fcc3ea19e99f8af8f7f) Thanks [@natemoo-re](https://github.com/natemoo-re)! - This version of `astro-icon` provides a new way to manage your icons, relying on Astro's official integration API rather than a managed remote API. Please see [the README](https://github.com/natemoo-re/astro-icon/tree/v1/packages/core#astro-icon) for more information. 144 | 145 | ## 0.8.2 146 | 147 | ### Patch Changes 148 | 149 | - [#153](https://github.com/natemoo-re/astro-icon/pull/153) [`3664cac3633330c3d19c8e1eb6ffa5c6b8848091`](https://github.com/natemoo-re/astro-icon/commit/3664cac3633330c3d19c8e1eb6ffa5c6b8848091) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes incompatability with Vite 5 by removing a deprecated method 150 | 151 | - [#148](https://github.com/natemoo-re/astro-icon/pull/148) [`d176a7da3b7332d459ec97c0af1667b6be9057fa`](https://github.com/natemoo-re/astro-icon/commit/d176a7da3b7332d459ec97c0af1667b6be9057fa) Thanks [@kripod](https://github.com/kripod)! - Fixes an edge case with `createIconPack` when a module cannot be resolved 152 | 153 | - [#141](https://github.com/natemoo-re/astro-icon/pull/141) [`832ac0523905f658cebd537d65c67b391d7c9b52`](https://github.com/natemoo-re/astro-icon/commit/832ac0523905f658cebd537d65c67b391d7c9b52) Thanks [@liruifengv](https://github.com/liruifengv)! - fix type import 154 | 155 | - [#149](https://github.com/natemoo-re/astro-icon/pull/149) [`f5640282120e4eaa947c695e02587604f3f8b1a6`](https://github.com/natemoo-re/astro-icon/commit/f5640282120e4eaa947c695e02587604f3f8b1a6) Thanks [@kripod](https://github.com/kripod)! - Improves the performance for `createIconPack`'s local icon resolution 156 | 157 | ## 0.8.1 158 | 159 | ### Patch Changes 160 | 161 | - [#106](https://github.com/natemoo-re/astro-icon/pull/106) [`23c032b`](https://github.com/natemoo-re/astro-icon/commit/23c032b41e462107b83c5ce1960f2c5098e2d174) Thanks [@stramel](https://github.com/stramel)! - docs: better docs on Icon Packs, styling, and fallback icon 162 | 163 | * [#109](https://github.com/natemoo-re/astro-icon/pull/109) [`4e5f0a9`](https://github.com/natemoo-re/astro-icon/commit/4e5f0a942af7e5515a901e91a2bcd2fc477fcd76) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Remove `vite/client` reference 164 | 165 | ## 0.8.0 166 | 167 | ### Minor Changes 168 | 169 | - [#42](https://github.com/natemoo-re/astro-icon/pull/42) [`ae0a7f7`](https://github.com/natemoo-re/astro-icon/commit/ae0a7f72358dee39a133663423b499e4525c06cb) Thanks [@germanz](https://github.com/germanz)! - Pass props to custom resolvers 170 | 171 | ### Patch Changes 172 | 173 | - [#56](https://github.com/natemoo-re/astro-icon/pull/56) [`60c7304`](https://github.com/natemoo-re/astro-icon/commit/60c7304368a7ca88fa2190bc8bfac5e8229e0f50) Thanks [@dwightjack](https://github.com/dwightjack)! - Fix Chrome not rendering icons using SVG gradients 174 | 175 | * [#64](https://github.com/natemoo-re/astro-icon/pull/64) [`2c75a4a`](https://github.com/natemoo-re/astro-icon/commit/2c75a4a6bc675492bee96aeac89c05f610f28831) Thanks [@stramel](https://github.com/stramel)! - Update Sprite context to track usages using `Astro.request` 176 | 177 | - [#61](https://github.com/natemoo-re/astro-icon/pull/61) [`41b0b76`](https://github.com/natemoo-re/astro-icon/commit/41b0b769a736420cbe2fe1ece44c71f16bcd0281) Thanks [@jasikpark](https://github.com/jasikpark)! - Update README to drop SVGO workaround recommendation 178 | 179 | * [#59](https://github.com/natemoo-re/astro-icon/pull/59) [`1a5ff6b`](https://github.com/natemoo-re/astro-icon/commit/1a5ff6bf59460ba1dc13b33339748c8d86891102) Thanks [@stramel](https://github.com/stramel)! - Use `node:` prefix on standard node dependencies 180 | 181 | ## 0.7.3 182 | 183 | ### Patch Changes 184 | 185 | - [#46](https://github.com/natemoo-re/astro-icon/pull/46) [`31b6eae`](https://github.com/natemoo-re/astro-icon/commit/31b6eaef63d229586933c5081e551c9b688360fb) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Another Vite 3 fix 186 | 187 | ## 0.7.2 188 | 189 | ### Patch Changes 190 | 191 | - [#44](https://github.com/natemoo-re/astro-icon/pull/44) [`3b5c5ff`](https://github.com/natemoo-re/astro-icon/commit/3b5c5ff5597678e95f0374ce2f974796af2f2e6b) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Small fix for vite 3 192 | 193 | ## 0.7.1 194 | 195 | ### Patch Changes 196 | 197 | - [`147001e`](https://github.com/natemoo-re/astro-icon/commit/147001eb2db7e6cbb8d0433be56fb86f79cf3a42) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix `Sprite` component for Astro v1.0.0 198 | 199 | ## 0.7.0 200 | 201 | ### Minor Changes 202 | 203 | - [#32](https://github.com/natemoo-re/astro-icon/pull/32) [`4cfc1ba`](https://github.com/natemoo-re/astro-icon/commit/4cfc1badfb5978829c1dfeb5b56491238a3a8e74) Thanks [@tony-sull](https://github.com/tony-sull)! - Removes the deprecation warning for assert in import.meta.globEager 204 | 205 | ### Patch Changes 206 | 207 | - [`3b29d89`](https://github.com/natemoo-re/astro-icon/commit/3b29d893bbb385c8e6e8fa51b421fefa17b050ac) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve warning when no sprites are found rather than throwing an error 208 | 209 | ## 0.6.1 210 | 211 | ### Patch Changes 212 | 213 | - [#30](https://github.com/natemoo-re/astro-icon/pull/30) [`940539b`](https://github.com/natemoo-re/astro-icon/commit/940539bf81ad205c9ca02082c1f5e2526570acfe) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Update package.json to include Astro keywords 214 | 215 | ## 0.6.0 216 | 217 | ### Minor Changes 218 | 219 | - [#26](https://github.com/natemoo-re/astro-icon/pull/26) [`21bfa28`](https://github.com/natemoo-re/astro-icon/commit/21bfa288c6c3606f5797a22350d8018cd7589a0a) Thanks [@matthewp](https://github.com/matthewp)! - `astro-icon` is now compatible with Astro's `--experimental-static-build` flag 220 | 221 | * [#26](https://github.com/natemoo-re/astro-icon/pull/26) [`21bfa28`](https://github.com/natemoo-re/astro-icon/commit/21bfa288c6c3606f5797a22350d8018cd7589a0a) Thanks [@matthewp](https://github.com/matthewp)! - # Breaking Changes 222 | 223 | - `astro-icon@0.6.0` is compatible with `astro@0.23.x` and up, but will no longer work in lower versions. 224 | 225 | - The `createIconPack` export has been moved from `astro-icon` to `astro-icon/pack`. 226 | 227 | You will likely see a Vite error that `createIconPack` is not defined until you update your import statement. 228 | 229 | ```diff 230 | - import { createIconPack } from "astro-icon"; 231 | + import { createIconPack } from "astro-icon/pack"; 232 | 233 | export default createIconPack({ package: "heroicons", dir: "outline" }) 234 | ``` 235 | 236 | ## 0.5.3 237 | 238 | ### Patch Changes 239 | 240 | - [`d998134`](https://github.com/natemoo-re/astro-icon/commit/d99813407e9bb0c043a7ff8d499031b667dfd894) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix issue with default `size` prop. 241 | 242 | ## 0.5.2 243 | 244 | ### Patch Changes 245 | 246 | - [#16](https://github.com/natemoo-re/astro-icon/pull/16) [`9ff5e7d`](https://github.com/natemoo-re/astro-icon/commit/9ff5e7d50ec94e2e0b9552c14b2bcd243fb2c48a) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix parallelism issue when fetching icons from the Icon service in a map 247 | 248 | ## 0.5.1 249 | 250 | ### Patch Changes 251 | 252 | - [`0217a71`](https://github.com/natemoo-re/astro-icon/commit/0217a716c7278e30a04de45f72e7a3cce5c65180) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Automatically prefix IDs using SVGO 253 | 254 | * [`330e465`](https://github.com/natemoo-re/astro-icon/commit/330e4654e160bcea8affd672e67afe69c2919cb2) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fail builds when icons cannot be fetched 255 | 256 | ## 0.5.0 257 | 258 | ### Minor Changes 259 | 260 | - [`e61559b`](https://github.com/natemoo-re/astro-icon/commit/e61559be5b530d0cc1e3479490ff23fd06158ef5) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Adds `` component. This will render `` internally, after all `` components have been rendered, solving a race condition. 261 | 262 | Deprecates ``, to be replaced with `` component. 263 | 264 | **Migrating from `` to ``** 265 | 266 | - Remove `Spritesheet` component. 267 | - Wrap your site content in ``. This also works inside of a layout component! 268 | 269 | ```diff 270 | --- 271 | - import { Sprite, Spritesheet } from 'astro-icon'; 272 | + import { Sprite } from 'astro-icon'; 273 | --- 274 | 275 | 276 | + 277 | 278 | - 279 | + 280 | 281 | ``` 282 | 283 | ## 0.4.0 284 | 285 | ### Minor Changes 286 | 287 | - [#7](https://github.com/natemoo-re/astro-icon/pull/7) [`3715ead`](https://github.com/natemoo-re/astro-icon/commit/3715ead35e090650d1ffe4af0493dcc3863c1255) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Add support for custom icon packs from local or remote sources. 288 | 289 | Add built-in icon packs powered by [Iconify](https://iconify.design/)! You can search for supported on icons on [Icônes](https://icones.js.org/). 290 | 291 | ## 0.3.0 292 | 293 | ### Minor Changes 294 | 295 | - [`62559e0`](https://github.com/natemoo-re/astro-icon/commit/62559e09db40482ab2fc6b4fdc001a6e38e9b7ad) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve SpriteSheet component by automatically including only referenced icon files 296 | 297 | ## 0.2.2 298 | 299 | ### Patch Changes 300 | 301 | - [`e201b6e`](https://github.com/natemoo-re/astro-icon/commit/e201b6e997c6b1cb25de2cc7d72524df0a816a55) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve documentation 302 | 303 | ## 0.2.1 304 | 305 | ### Patch Changes 306 | 307 | - Fix issue with published package 308 | 309 | ## 0.2.0 310 | 311 | ### Minor Changes 312 | 313 | - [`52bb8ff`](https://github.com/natemoo-re/astro-icon/commit/52bb8ff24e1dd1c26f6eadc2bb08d8e7f1ec3573) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Add `` and `` components that take advantage of `` 314 | --------------------------------------------------------------------------------