Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ constrains belongs there, not here.
## Writing

- NZ English everywhere ("colour", "behaviour", "initialise").
- Match a document's length to what it needs. Cover the substance, then
stop: no filler sections, restated summaries or boilerplate.
- Single-line commit messages, `git log --oneline` style. Add a body only to
explain why, and only for behaviour or type changes.
- No conventional-commit prefixes (`feat:`, `fix:`, `chore(deps):`) in commit
Expand Down Expand Up @@ -44,17 +46,11 @@ through `await waitFor(...)`. The warm-cache loading test is the one deliberate
exception: it needs the cache to hit, so it uses a fixed URL no other test
touches.

jsdom has no accessibility layer and no paint, so the suite pins the ARIA
wiring as markup and can go no further: whether a screen reader does anything
with that markup is outside what any test here can answer. That is this repo's
blind spot rather than a shared one, because the wiring lives here —
svg-injector ships no ARIA behaviour of its own. `test/manual/` is the check for
those questions: a node server and a page driven by hand under VoiceOver. It is
not run by `npm test` and not wired into CI, deliberately, since the instrument
is a real screen reader and automating it would mean simulating the thing it
exists to escape. Run it and record the result in the PR when you change the
`test/manual/` is a hand-driven screen-reader harness, deliberately outside
`npm test` and CI. Run it and record the result in the PR when you change the
ARIA wiring or the `loading` element's lifecycle, and update its recorded run in
the same commit as any deliberate change to either.
the same commit as any deliberate change to either. `test/manual/README.md`
covers why it exists and what it can and cannot answer.

Raising a `size-limit` budget in `package.json` is a decision, not a fix. Find
what grew first, and say why in the commit message.
Expand Down
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@

> A React component that injects SVG into the DOM.

[Background](#background) | [When To Use This](#when-to-use-this) | [Basic Usage](#basic-usage) | [API](#api) | [Live Examples](#live-examples) | [Installation](#installation) | [Security](#security) | [FAQ](#faq) | [Contributing](#contributing) | [License](#license)
[When To Use This](#when-to-use-this) | [Basic Usage](#basic-usage) | [API](#api) | [Live Examples](#live-examples) | [Installation](#installation) | [Security](#security) | [FAQ](#faq) | [Contributing](#contributing) | [License](#license)

## Background
## When To Use This

This component uses [@tanem/svg-injector](https://github.com/tanem/svg-injector) to fetch an SVG from a given URL and inject its markup into the DOM ([why?](https://github.com/tanem/svg-injector#background)). Fetched SVGs are cached, so multiple uses of the same SVG only require a single request.

## When To Use This

Injection costs a network request and two wrapper elements, and it earns that cost in one case: the SVG's URL isn't known until the app runs, and the markup has to be reachable by CSS. An `<img>` tag renders an SVG but its contents can't be styled, animated or scripted from the page.

- **SVGs live in your repo and are known at build time.** Reach for a build-time transform - [SVGR](https://react-svgr.com), [vite-plugin-svgr](https://github.com/pd4d10/vite-plugin-svgr), or your bundler's SVG loader. They compile each file to a React component, so there's no runtime fetch, and unused icons are tree-shaken out.
Expand Down Expand Up @@ -249,11 +247,9 @@ Related issues and PRs:
Can I use data URIs or inline SVG strings?
</summary>

`data:image/svg+xml` URLs are supported (both URL-encoded and base64-encoded). The underlying library parses the SVG content directly from the data URL using `DOMParser`, without making a network request. This is useful when bundlers like Vite inline small SVGs as data URIs. See the [data URL example](https://github.com/tanem/react-svg/tree/master/examples/data-url) for details.

Inline SVG strings (raw markup passed directly as the `src` prop) are **not** supported. If you already have the SVG markup as a string (for example, a dynamically generated chart), consider parsing it with `DOMParser` and appending the result yourself, or rendering it with `dangerouslySetInnerHTML`. These approaches avoid the fetch step entirely and will also avoid the brief flash that occurs when `react-svg` re-injects on `src` change.
Data URIs yes, inline strings no. `data:image/svg+xml` URLs are parsed directly with `DOMParser` and make no network request - see [`src`](#src) and the [data URL example](https://github.com/tanem/react-svg/tree/master/examples/data-url).

**Security note:** inserting SVG strings into the DOM bypasses React's built-in escaping and can expose your application to XSS if the content is not trusted. If the SVG originates from user input or a third party, sanitise it first with a library like [DOMPurify](https://github.com/cure53/DOMPurify) before inserting it into the page. The same applies to fetched SVGs - see [Security](#security).
Raw markup passed as `src` is **not** supported. If you already hold the SVG as a string - a generated chart, say - parse it with `DOMParser` and append the result yourself, or render it with `dangerouslySetInnerHTML`. Both skip the fetch, and the brief flash when `react-svg` re-injects on a `src` change. Either way you're inserting markup outside React's escaping, so [Security](#security) applies.

</details>

Expand Down
10 changes: 3 additions & 7 deletions examples/accessibility/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Accessibility Example

## Available Scripts
Sets `title` and `desc`, so the injected SVG carries `<title>` and `<desc>`
elements wired to it through `aria-labelledby` and `aria-describedby`.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
11 changes: 4 additions & 7 deletions examples/api-usage/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# ReactSVG API Usage Example

## Available Scripts
Every prop at once, including the ones left at their defaults elsewhere -
`evalScripts`, `httpRequestWithCredentials`, `renumerateIRIElements`,
`useRequestCache` and `wrapper`.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
9 changes: 2 additions & 7 deletions examples/basic-usage/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# ReactSVG Basic Usage Example

## Available Scripts
The smallest thing that works: a single `src`, no other props.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/before-injection/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Before Injection Example

## Available Scripts
Uses `beforeInjection` to class, style and rewrite the SVG element in the window
between the fetch landing and the element reaching the DOM.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/css-animation/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG CSS Animation Example

## Available Scripts
Animates the injected SVG by adding a class in `afterInjection`, which is the
first point at which the element is in the DOM and animatable.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/css-in-js/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG CSS-in-JS Example

## Available Scripts
Styles the injected SVG with glamor, relying on unrecognised props being spread
onto the outer wrapper so the generated class reaches the DOM.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/data-url/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Data URL Example

## Available Scripts
Injects from `data:image/svg+xml` URLs, both URL-encoded and base64, as a
bundler like Vite produces for small SVGs. No network request is made.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/external-stylesheet/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG External Stylesheet Example

## Available Scripts
Styles the injected SVG from a plain stylesheet, reaching it through a class on
the wrapper. Injected markup is part of the page, so ordinary CSS applies.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
11 changes: 4 additions & 7 deletions examples/fallbacks/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# ReactSVG Fallbacks Example

## Available Scripts
`fallback` as a class, function and string component, and the two cases that
aren't a failed fetch: an error thrown from `beforeInjection` or
`afterInjection`.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/iframe/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Iframe Example

## Available Scripts
Injects inside an iframe, where the wrapper belongs to a different document than
the one the app was loaded into.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/loading/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Loading Example

## Available Scripts
Shows a spinner through `loading` while the SVG is fetched, once on its own and
once alongside a `fallback` for a URL that fails.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
13 changes: 3 additions & 10 deletions examples/no-extension/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
# ReactSVG No Extension Example

Demonstrates that react-svg handles SVG files served without a file extension,
provided the server responds with an appropriate content type.
An SVG served without a file extension, which works provided the server responds
with an appropriate content type.

## Available Scripts

In the project directory, you can run:

### `npm start`

Builds the app with Vite, starts an Express server on port 8080, and opens the
browser automatically.
`npm start` builds the app, serves it on port 8080 and opens the browser.
10 changes: 3 additions & 7 deletions examples/sprite-usage/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG Sprite Usage Example

## Available Scripts
Pulls individual icons out of one `sprite.svg` through fragment identifiers
(`sprite.svg#icon-star`), sizing each one in `beforeInjection`.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
20 changes: 4 additions & 16 deletions examples/ssr/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
# ReactSVG SSR Example

This project was bootstrapped with [Next.js](https://nextjs.org/).

`ReactSVG` is published with a `"use client"` directive, so it can be imported
directly into a Server Component - see `app/page.js`. Props that take functions
(`afterInjection`, `beforeInjection`, `fallback`, `loading`) can't cross the
server/client boundary, so pass those from your own Client Component.

## Available Scripts

In the project directory, you can run:

### `npm run dev`

Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
directly into a Next.js Server Component - see `app/page.js`. Props that take
functions (`afterInjection`, `beforeInjection`, `fallback`, `loading`) can't
cross the server/client boundary, so pass those from your own Client Component.

The page will reload if you make edits.<br>
You will also see any lint errors in the console.
`npm run dev`, then open <http://localhost:3000>.
11 changes: 4 additions & 7 deletions examples/styled-components/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# ReactSVG Styled Components Example

## Available Scripts
Wraps `ReactSVG` in `styled()` and reaches the injected SVG through a descendant
selector, since the styled wrapper sits two elements above it. From
[#1911](https://github.com/tanem/react-svg/issues/1911).

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
10 changes: 3 additions & 7 deletions examples/svg-wrapper/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# ReactSVG SVG Wrapper Example

## Available Scripts
`wrapper="svg"`, mounted twice: once inside an existing SVG document and once
inside plain HTML.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
9 changes: 2 additions & 7 deletions examples/typescript/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# ReactSVG Typescript Example

## Available Scripts
Basic usage from TypeScript, against the bundled type declarations.

In the project directory, you can run:

### `npm start`

Runs the app in development mode.\
Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
`npm start`, then open <http://localhost:5173>.
Loading
Loading