Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inlined SVG does not escape { and } characters #18756

Open
7 tasks done
Bastian opened this issue Nov 25, 2024 · 1 comment
Open
7 tasks done

Inlined SVG does not escape { and } characters #18756

Bastian opened this issue Nov 25, 2024 · 1 comment

Comments

@Bastian
Copy link

Bastian commented Nov 25, 2024

Describe the bug

When inlining SVGs, Vite does not escape special characters such as curly brackets.

example.svg:

<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
  <style>
    circle {
      fill: gold;
      stroke: maroon;
      stroke-width: 2px;
    }
  </style>

  <circle cx="5" cy="5" r="4" />
</svg>

entry-server.js:

import exampleSvg from './example.svg';

export function render() {
  const html = `<img height="100" width="100" src="${exampleSvg}" alt="Example" />`;
  return { html };
}

Output:

<img height="100" width="100" src="data:image/svg+xml,%3csvg%20viewBox='0%200%2010%2010'%20xmlns='http://www.w3.org/2000/svg'%3e%3cstyle%3e%20circle%20{%20fill:%20gold;%20stroke:%20maroon;%20stroke-width:%202px;%20}%20%3c/style%3e%3ccircle%20cx='5'%20cy='5'%20r='4'%20/%3e%3c/svg%3e" alt="Example">

This is flagged by https://validator.w3.org/ as an error:
image

I'm not 100% sure if it's a bug in the validator or in Vite, but after digging through RFCs for way too long, I think it's a bug in Vite.

Why I think this is a Vite bug

RFC 2397 states

Without ";base64", the data (as a sequence of octets) is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding of URLs for octets outside that range.

Unfortunately, they do not define what safe URL characters are. However, there is a formal definition of the syntax of a data URL in Chapter 3:

dataurl    := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype  := [ type "/" subtype ] *( ";" parameter )
data       := *urlchar
parameter  := attribute "=" value

urlchar is a reference to RFC2396 which is superseded by RFC3986.

The deprecated RFC2396 does not define a urlchar but a uric, which I believe is what is meant.
In the newer RFC3986, appendix D.2 provides a convenient translation of the now obsolete uric:

   +----------------+--------------------------------------------------+
   | obsolete rule  | translation                                      |
   +----------------+--------------------------------------------------+
   | uric           | unreserved / pct-encoded / ";" / "?" / ":"       |
   |                |  / "@" / "&" / "=" / "+" / "$" / "," / "/"       |
   +----------------+--------------------------------------------------+

The relevant unreserved and pct-encoded are defined in Section 2.3. and Section 2.1.:

unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"

pct-encoded = "%" HEXDIG HEXDIG

This also seems to be consistent with which characters JavaScript's encodeURI function encodes.

Reproduction

https://stackblitz.com/edit/vite-ssr-28jd81?file=src%2Fexample.svg

Steps to reproduce

No response

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.20.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    vite: ^5.4.9 => 5.4.11

Used Package Manager

npm

Logs

No response

Validations

@sapphi-red
Copy link
Member

I'm not 100% sure if it's a bug in the validator or in Vite, but after digging through RFCs for way too long, I think it's a bug in Vite.

It's not a valid data URI in RFC 2397, but the browsers that follows the Fetch Standard (all evergreen browsers) are possible to parse it correctly.
The Fetch Standard defines a decode steps that can parse data URI that contains non-uric.
It's a bit bad behavior, but it reduces the file size significantly and these kinds of non spec-compliant data URIs are ubiquitous as mini-svg-data-uri package that generates them was recommended by url-loader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants