npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@h-k-dev/angular-inline-svg

v1.5.1

Published

A lightweight, signal-based Angular directive for inlining SVGs into the DOM, with caching, fallbacks, attribute manipulation, and accessibility defaults.

Readme

@h-k-dev/angular-inline-svg

A tiny, signal-based Angular directive that fetches an SVG by URL and inlines it directly into the DOM, so you can style and script it with CSS and JavaScript like any other element. Think of this as the modern Angular counterpart to react-inlinesvg.

💡 Legacy Browser / Older Angular Support: This package is heavily optimized for modern, cutting-edge environments. If you need to support legacy browsers or older versions of Angular, please use ng-inline-svg-2.

My objectives is to stay in the browser. While this package will NEVER adopt SSR support out of the box, I will expose functions for you to build your own pipeline on server side and keep the package as lean as possible at build time. As time goes more injection at configuration level will permit you to implement your own Hydration Strategy that hopefully allows a seemless adoption for SSR implementation.

Features

  • Inline, not <img> — the SVG lands in the DOM so currentColor, CSS, and JS all work.
  • Reactive — built on Angular signals and resource(); re-renders automatically when inputs change.
  • Caching — bounded LRU + TTL cache with in-flight request de-duplication.
  • Fallbacks — supply a fallbackSVG URL, with a built-in generic placeholder as a last resort.
  • Attribute manipulation — add or strip attributes on the inserted <svg> (e.g. width, fill).
  • Accessible by default — sets focusable="false" and aria-hidden="true" unless you provide a semantic hint.
  • SSR-safe — bails out cleanly on the server and only touches the DOM in the browser.
  • Hardened — strips <script> tags and inline on* handlers as defense-in-depth.

Installation

npm install @h-k-dev/angular-inline-svg

Quick start

The directive is standalone — just import it where you need it.

import { Component } from '@angular/core';
import { AngularInlineSvg } from '@h-k-dev/angular-inline-svg';

@Component({
  selector: 'app-logo',
  imports: [AngularInlineSvg],
  template: `<span [inlineSVG]="'assets/icons/logo.svg'"></span>`,
})
export class LogoComponent {}

The fetched SVG is appended to the host element, so the markup above renders as:

<span><svg ...>...</svg></span>

Configuration

Configure the directive once at the application root with provideInlineSvg():

import { ApplicationConfig } from '@angular/core';
import { provideInlineSvg } from '@h-k-dev/angular-inline-svg';

export const appConfig: ApplicationConfig = {
  providers: [
    provideInlineSvg({
      baseUrl: 'assets/icons',
      cacheMaxEntries: 100,
      cacheTtlMs: 5 * 60 * 1000, // 5 minutes
    }),
  ],
};

| Option | Type | Default | Description | | ----------------- | ------------------ | ------------- | -------------------------------------------------------------------------------------------- | | baseUrl | string | '' | Prepended to relative URLs when resolveSVGUrl is enabled. | | cacheMaxEntries | number | 100 | Maximum cached SVGs before least-recently-used eviction. | | cacheTtlMs | number | 300000 | How long (ms) a cached SVG stays fresh before it is refetched. | | cacheParsedElements | boolean | true | Also keep one parsed + scrubbed master element per cached URL so repeat icons skip parse/scrub and just clone it. Disable to keep cache entries text-only. | | fetcher | InlineSvgFetcher | native fetch| DI-free custom fetcher. For DI-based fetchers (e.g. HttpClient), use provideInlineSvgFetcher. |

Custom fetchers are responsible for their own content-type validation. The built-in default rejects responses that aren't image/svg+xml or text/plain.

Custom fetcher

By default the directive loads SVGs with the native fetch API. You can swap in your own transport - to add auth headers, go through an interceptor stack, or use a different HTTP client. A fetcher is any promise-based function matching:

type InlineSvgFetcher = (url: string, abortSignal: AbortSignal) => Promise<string>;

Honor the abortSignal so in-flight requests are cancelled when the directive is destroyed or its URL changes.

Native fetch with custom headers

For a DI-free fetcher, pass it straight to provideInlineSvg:

import { provideInlineSvg } from '@h-k-dev/angular-inline-svg';

provideInlineSvg({
  fetcher: async (url, signal) => {
    const res = await fetch(url, {
      signal,
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
    return res.text();
  },
});

Axios

Axios supports AbortSignal natively via its signal option:

import axios from 'axios';
import { provideInlineSvg } from '@h-k-dev/angular-inline-svg';

provideInlineSvg({
  fetcher: (url, signal) =>
    axios.get<string>(url, { signal, responseType: 'text' }).then((res) => res.data),
});

Angular HttpClient

HttpClient needs dependency injection, so build the fetcher inside an injection context with provideInlineSvgFetcher. Bridge the abortSignal to unsubscription so aborts actually cancel the request:

import { inject } from '@angular/core';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { firstValueFrom, fromEvent, takeUntil } from 'rxjs';
import { provideInlineSvgFetcher } from '@h-k-dev/angular-inline-svg';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    provideInlineSvgFetcher(() => {
      const http = inject(HttpClient);
      return (url, signal) =>
        firstValueFrom(
          http
            .get(url, { responseType: 'text' })
            .pipe(takeUntil(fromEvent(signal, 'abort'))),
        );
    }),
  ],
};

API

Inputs

| Input | Type | Default | Description | | --------------------- | ----------------------------------------- | ------- | -------------------------------------------------------------------------------------------- | | inlineSVG | string (required) | — | URL of the SVG to load and inline. | | fallbackSVG | string | — | URL loaded instead if the main inlineSVG request fails. | | resolveSVGUrl | boolean | true | When true, relative URLs are resolved against the configured baseUrl. | | setSVGAttributes | Record<string, string \| number \| boolean> | — | Attributes applied to the root <svg> after load (e.g. { width: 24, fill: 'red' }). | | removeSVGAttributes | readonly string[] | — | Attribute names stripped from the <svg> and all descendants after load. | | useCache | boolean | true | When true, the SVG is cached and reused for subsequent requests. | | preParse | (rawSvg: string) => string | — | Optional hook to transform/sanitize the raw SVG string before parsing (e.g. via DOMPurify). |

Outputs

| Output | Payload | Description | | -------- | ------------ | ----------------------------------------------------------------- | | loaded | SVGElement | Emits the inserted <svg> element once it is in the DOM. | | failed | Error | Emits when loading or parsing fails (after any fallback fails). |

Usage examples

Setting and removing attributes

<span
  [inlineSVG]="'icon.svg'"
  [setSVGAttributes]="{ width: 32, height: 32, fill: 'currentColor' }"
  [removeSVGAttributes]="['width', 'height']"
></span>

Fallback and event handling

<span
  [inlineSVG]="'maybe-missing.svg'"
  [fallbackSVG]="'placeholder.svg'"
  (loaded)="onLoaded($event)"
  (failed)="onFailed($event)"
></span>
onLoaded(svg: SVGElement) {
  console.log('SVG inserted', svg);
}

onFailed(err: Error) {
  console.error('SVG failed to load', err);
}

Sanitizing untrusted SVGs

For SVGs from untrusted sources, run them through a sanitizer such as DOMPurify using the preParse hook:

import DOMPurify from 'dompurify';

protected readonly sanitize = (raw: string): string => DOMPurify.sanitize(raw);
<span [inlineSVG]="untrustedUrl" [preParse]="sanitize"></span>

Security

The directive parses markup in a detached element (keeping it out of Angular's sanitizer so the <svg> survives) and, as defense-in-depth, removes <script> tags and inline on* event handlers. This is not a full sanitizer. For genuinely untrusted input, always route the SVG through DOMPurify via preParse.

Accessibility

After loading, the directive applies sensible defaults to the root <svg>:

  • focusable="false" — keeps the SVG out of the tab order.
  • aria-hidden="true" — treats the icon as decorative.

If you provide any of role, aria-label, aria-labelledby, or aria-hidden via setSVGAttributes, the directive leaves it visible to screen readers:

<span
  [inlineSVG]="'search.svg'"
  [setSVGAttributes]="{ role: 'img', 'aria-label': 'Search' }"
></span>

License

MIT