SVG as inline datauri
thejskhan opened this issue · comments
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
I ran into the same problem, would love to have this.
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" />
)
...