-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinlineSVG.js
More file actions
42 lines (37 loc) · 1.29 KB
/
inlineSVG.js
File metadata and controls
42 lines (37 loc) · 1.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import React, { useRef, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
const InlineSVG = ({ src, ...otherProps }) => {
const svgId = Math.random()
.toString(36)
.slice(2, 12);
const processedSVG = useMemo(() => {
const prefix = `svg-${svgId}`;
return src.replace(
/<style>([\s\S]*?)<\/style>|class="([^"]+)"|id="([^"]+)"/g,
(match, styles, classAttr, idAttr) => {
if (styles) {
return `<style>${styles
// Class selectors: only match when followed by { or , (selector context)
.replace(/(^|[^\w-])\.([a-zA-Z_][\w-]*)(?=\s*[{,])/gm, `$1.${prefix}-$2`)
// ID selectors: only match when followed by { or , (selector context)
.replace(/(^|[^\w-])#([a-zA-Z_][\w-]*)(?=\s*[{,])/gm, `$1#${prefix}-$2`)}</style>`;
}
if (classAttr) {
return `class="${classAttr
.split(/\s+/)
.map(c => `${prefix}-${c}`)
.join(' ')}"`;
}
if (idAttr) {
return `id="${prefix}-${idAttr}"`;
}
return match;
},
);
}, [svgId, src]);
return <div dangerouslySetInnerHTML={{ __html: processedSVG }} {...otherProps} />;
};
InlineSVG.propTypes = {
src: PropTypes.string.isRequired,
};
export default InlineSVG;