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

SVG as inline datauri #18

Open
2khan opened this issue Oct 13, 2022 · 3 comments
Open

SVG as inline datauri #18

2khan opened this issue Oct 13, 2022 · 3 comments

Comments

@2khan
Copy link

2khan commented Oct 13, 2022

Hello @giekaton !

Abstract

I am building a web with users and didn't want to use the "default_user.svg" since it is boring. Found this package and fell in love with it immediately.

Problem

So I went ahead integrated it with my React project and since I don't want to "unsafely render svg text" on my web, I tried inline SVG like the following:

// React Component
const Avatar = () => {
  const svgString = useMemo(() => {
    return multiavatar("hello world!", false)
  }, [])

  return (
    <img src={`data:image/svg+xml,${svgString}`} alt="avatar" />
  )
}

The above did not render because # is included in the svgString.

Solution

So I tried encoding the string as such:

// from "https://github.com/tigt/mini-svg-data-uri"
// "modified" a bit
const REGEX = {
    whitespace: /\s+/g,
    urlHexPairs: /%[\dA-F]{2}/g,
    quotes: /"/g,
}

function specialHexEncode(match: string) {
    switch (match) {
        case '%20': return ' ';
        case '%3D': return '=';
        case '%3A': return ':';
        case '%2F': return '/';
        default: return match.toLowerCase();
    }
}

export const toDataURI = (string: string) =>
    encodeURIComponent(string)
        .trim()
        .replace(REGEX.whitespace, ' ')
        .replace(REGEX.quotes, "'")
        .replace(REGEX.urlHexPairs, specialHexEncode)

The above code was used as return toDataURI(multiavatar("hello world!", false)) and what do you know, it renders!

Advantages

For developers using multiavatar on the client side can easily render the avatars with img tag.

Request

multiavatar function to include optional parameter asDataURI?: boolean (defaults to false)

Real Life Usage

// React Component
const Avatar = () => {
  const svgString = useMemo(() => {
    // May also support options object?
    // return multiavatar("hello world", {
    //   asDataURI: true,
    //   sansEnv: false,
    // })
    
    // expecting `data:image/svg+xml,{encodedSVGstring}`
    return multiavatar("hello world", false, , true);
  }, [])

  return (
    <img src={svgString} alt="avatar" />
  )
}

Edit:

  • Mentioned @giekaton because I wanted to say hello ✋
  • Added expectation returned from multiavatar @ Real Life Usage
@e-reifer
Copy link

I ran into the same problem, would love to have this.

@2khan
Copy link
Author

2khan commented Oct 27, 2022

You can use the following function to turn Multiavatar SVGs to DataURI

// Utilities

const REGEX = {
    whitespace: /\s+/g,
    urlHexPairs: /%[\dA-F]{2}/g,
    quotes: /"/g,
}

function specialHexEncode(match: string) {
    switch (match) {
        case '%20': return ' ';
        case '%3D': return '=';
        case '%3A': return ':';
        case '%2F': return '/';
        default: return match.toLowerCase();
    }
}

export const toDataURI = (string: string) =>
    `data:image/svg+xml,${encodeURIComponent(string)
        .trim()
        .replace(REGEX.whitespace, ' ')
        .replace(REGEX.quotes, "'")
        .replace(REGEX.urlHexPairs, specialHexEncode)}`

Usage

...

const svg = toDataURI(multiavatar("your-avatar-string")) // returns valid DataURI

return (
   <img src={svg} alt="avatar" />
)
...

@sy0uta1k0n
Copy link

@2khan i have 2 say, u r my hero ! fix my issue !

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

No branches or pull requests

3 participants