Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anhtuank7c/ed9df4714b455f6d1cbd0ecd93d2f97f to your computer and use it in GitHub Desktop.
Save anhtuank7c/ed9df4714b455f6d1cbd0ecd93d2f97f to your computer and use it in GitHub Desktop.
Convert Illustrator SVG export into cross-platform CSS independent mode. CSS rule and style inlining, group gradients into a definitions tag, remove elements with display set to none, make colors hex. Works with react-native-web react-native-svg and svgs to give cross-platform web and native mobile rendering of any SVG produced in Illustrator.
/*
Import https://raw.githubusercontent.com/MikeMcl/decimal.js/master/decimal.js first
Then run this.
Then put it into the SVG to JSX Online Converter http://svg-jsx.patmoody.com/
Then find (e.g. using WebStorm) all occurences of the regexp </?.
Select all matches (the first letter of every react tag) and toggle case / replace with upper case (to use cross-platform react components from the svgs library)
Finally, wrap in a pure function and make sure to import all needed components:
import React from "react";
import {
Circle,
ClipPath,
Defs,
Ellipse,
G,
Image,
Line,
LinearGradient,
Path,
Polygon,
Polyline,
RadialGradient,
Rect,
Stop,
Svg,
Symbol,
Text,
TextPath,
Use
} from "svgs";
export default () => <Svg />;
*/
(function() {
function rgb2hex(input) {
var rgb = input.match(
/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i
);
return rgb && rgb.length === 4
? "#" +
("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3], 10).toString(16)).slice(-2)
: input;
}
/* Inline all rules from all CSS stylesheets as attributes on all matching elements and remove class attribute */
let styles = Array.from(document.querySelectorAll("style"));
styles.forEach(styleSheet => {
Array.from(styleSheet.sheet.cssRules).forEach(rule => {
if (rule.style.display === "none") {
// Remove hidden elements
Array.from(document.querySelectorAll(rule.selectorText)).forEach(el => {
el.parentElement.removeChild(el);
});
} else {
const styles = [];
for (let [key, value] of Object.entries(rule.style)) {
if (key !== "cssText" && value) {
/* Convert rgba? values to hex */
styles.push([key, rgb2hex(value.replace(/"/g, ""))]);
}
}
Array.from(document.querySelectorAll(rule.selectorText)).forEach(el => {
styles.forEach(([key, value]) => {
el.setAttribute(key, value);
});
});
}
});
});
styles.forEach(styleSheet => {
Array.from(styleSheet.sheet.cssRules).forEach(rule => {
Array.from(document.querySelectorAll(rule.selectorText)).forEach(el => {
el.removeAttribute("class");
});
});
styleSheet.parentElement.removeChild(styleSheet);
});
/* Move inline CSS style values into element attributes */
Array.from(document.querySelectorAll("[style]")).forEach(el => {
for (let [key, value] of Object.entries(el.style)) {
if (key !== "cssText" && value) {
el.setAttribute(key, rgb2hex(value));
}
}
el.removeAttribute("style");
});
const gradients = Array.from(
document.querySelectorAll("linearGradient, radialGradient")
);
/* Move gradients inside of a defs tag, convert offsets from scientific notation to decimal notation */
if (gradients.length) {
if (typeof Decimal !== "undefined") {
Array.from(document.querySelectorAll("stop")).forEach(el => {
const offset = el.getAttribute("offset");
const newOffset = new Decimal(offset).toFixed();
el.setAttribute("offset", newOffset);
});
}
let def = document.createElement("defs");
gradients.forEach(el => def.appendChild(el));
let svg = document.querySelector("svg");
svg.insertBefore(def, svg.firstChild);
svg.innerHTML = svg.innerHTML
.replace(/stopColor/g, "stop-color")
.replace(/stopOpacity/g, "stop-opacity");
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment