convert-svg-react
Version:
Converts SVG XML code to be used as ReactJS component.
264 lines (212 loc) • 9.49 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var Format = require('./format');
var _require = require("./constants"),
stylePattern = _require.stylePattern,
isColan = _require.isColan,
isSemiColan = _require.isSemiColan,
isStyle = _require.isStyle,
isColorPattern = _require.isColorPattern,
isStopOpacity = _require.isStopOpacity,
isClassPattern = _require.isClassPattern,
isxmlPattern = _require.isxmlPattern,
cssObjects = _require.cssObjects,
isTitle = _require.isTitle,
enabledBackground = _require.enabledBackground,
isVersion = _require.isVersion,
isXML = _require.isXML,
isAdobeComment = _require.isAdobeComment;
/**
* Class to create new stringed svg element
*
*/
var Convert = /*#__PURE__*/function () {
/**
*
* @param {String} string - path to svg file ex: './pathto/my.svg'
*
*/
function Convert(string) {
(0, _classCallCheck2["default"])(this, Convert);
this.string = string;
this.svgCSS = '';
this.removeStyleElement = false;
}
/**
* @property {Function} checkString Reads file from path given by client
* @returns {object}
*/
(0, _createClass2["default"])(Convert, [{
key: "checkString",
value: function checkString(string) {
if (typeof this.string !== 'string') {
console.log('not a string');
return {
error: "<h1>File path or file is not of string path.</h1>"
};
} else return string;
}
/** Adds a string version of inline style element to be used as JSX
* @property {Function} stringify_STYLE_ELEM - Optional if user wants to leave style element in svg xml document
* @param {String} string - Newly indented string
*/
}, {
key: "stringify_STYLE_ELEM",
value: function stringify_STYLE_ELEM(string) {
// True to return string of <style type="text/css"> .someElement{someTyle:#A5A5A5;} </style>
// <style type="text/css">{
// '.photo-st0{fill:#C13838;}'+
// }
// </style>
// Or leave it, stringify it and use it within React
if (stylePattern.test(string)) {
if (this.removeStyleElement) {
this.string = this.string.replace(stylePattern, ''); // Where the svg Style element exist for client
this.svgCSS = string.match(stylePattern)[0].replace(/\t/g, ' ');
} else {
var CSSobjects = string.match(cssObjects);
var length = CSSobjects.length;
var _toString = '';
for (var i = 0; i < length; i++) {
var element = CSSobjects[i]; // If only one css object exist
if (length === 1) {
_toString += element.replace(/(\..*;})/i, '<style type="text/css">{\n"$1"\n}</style>');
break;
} // Replaces first line
if (i === 0) {
_toString += element.replace(/(\..*;})/i, '<style type="text/css">{\n"$1"+\n');
} // Replaces last line
else if (i === length - 1) {
_toString += element.replace(/(\..*;})/i, '"$1"\n}</style>');
} // Replaces every other line
else {
_toString += element.replace(/(\..*;})/i, ' "$1"+\n');
}
}
return this.string.replace(/<style.*[\s\S]*<\/style>/gi, _toString);
}
} else return string;
}
/**
*
* @property {Function} inlineStyleJSX - Looks for all xml attributes that need to be replaced
* @param {String} string string after some replacement of attributes
* @param {object} Format Class object to format string; callback
* @returns {Object} - To strings sent; One for rendered version of svg and one for copy within Textarea
*/
}, {
key: "inlineStyleJSX",
value: function inlineStyleJSX(string, Format) {
var cssStringed = this.stringify_STYLE_ELEM(string);
var individual_lines = cssStringed.split('\n');
var i = individual_lines.length;
var regEx = new RegExp(/(style=)"(.*:.*;)"/, 'i');
var newStyleObj = '';
var newSTring = []; //Goes through each line
while (i--) {
// Checks for only lines that contain style attributes
if (regEx.test(individual_lines[i])) {
var split_style_obj = individual_lines[i].match(regEx)[2].split(';'); // Adds quotes to the values: [ 'display:block', 'overflow:hidden', 'height: 100', '' ] to display:"block",overflow:"hidden",height:"100"
split_style_obj.forEach(function (string) {
return newStyleObj += string.replace(/(.*:)(\s?[#\w\d\.]+)/, '$1"$2",');
}); // replaces style="display:block;overflow:hidden;height:100;" to style={{display:"block",overflow:"hidden",height:"100"}}
var x = individual_lines[i].replace(/(style=)"(.*:.*;)"/i, "$1{{".concat(newStyleObj, "}}"));
newSTring.unshift(x + '\n');
newStyleObj = '';
} else {
newSTring.unshift(individual_lines[i] + '\n');
}
}
return Format.indent(newSTring.join(''));
}
/**
*
* @property {Function} findAndReplace - Looks for all xml attributes that need to be replaced
* @returns {Object} - To strings sent; One for rendered version of svg and one for copy within Textarea
*/
}, {
key: "findAndReplace",
value: function findAndReplace() {
var _this = this;
var string = this.string;
this.checkString(string);
if (!(0, _typeof2["default"])(string)) return "<div>Must be a valid string</div>";
if (isxmlPattern.test(string)) {
switch (true) {
case /xmlns:xlink/gi.test(string):
this.string = this.string.replace(/xmlns:xlink=".+\/xlink"\s/gi, '');
case /xml:space/gi.test(string):
this.string = this.string.replace(/xml:space/gi, 'xmlSpace');
case /xlink:href/gi.test(string):
this.string = this.string.replace(/xlink:href/gi, 'href');
}
}
/* remove typical attributes and unnedded extra left over adobe file additions */
switch (true) {
case enabledBackground.test(string):
this.string = this.string.replace(/style="enable-background.+"\s/g, '');
case isColorPattern.test(string):
this.string = this.string.replace(isColorPattern, 'stopColor');
case isStopOpacity.test(string):
this.string = this.string.replace(isStopOpacity, 'stopOpacity');
case isXML.test(string):
this.string = this.string.replace(isXML, '');
case isClassPattern.test(string):
this.string = this.string.replace(isClassPattern, 'className=');
case isTitle.test(string):
this.string = this.string.replace(/<title>.*<\/title>/, '');
case isVersion.test(string):
this.string = this.string.replace(isVersion, '');
case isAdobeComment.test(string):
this.string = this.string.replace(isAdobeComment, '');
}
this.string = this.string.replace(/(<.*style="stopColor|<.*style="stopColor)(:.*)("\/>)/gmi, '$1$2;$3'); // Remove </path> and add / to end of path => />
this.string = this.string.replace(/(<path.*)(>)\n?(<\/path>)/igm, '$1/$2');
function catenate(match, p1, p2, p3) {
return p1 + p2.toUpperCase() + p3;
}
var hasDashedAttributes = function hasDashedAttributes(string) {
return /\s\w+-\w+=/ig.test(string);
}; // Checks if style attributes not concatinated exist ex: font-size => fontSize, stroke-width => strokeWidth ...
var findAttributedDashes = function findAttributedDashes(string) {
var stringArr = [];
if (hasDashedAttributes(string)) {
var individual_lines = string.split('\n');
var i = individual_lines.length;
while (i--) {
var attribute = individual_lines[i].match(/\s(?:\w|=")+-\w+(=|:)/ig);
if (attribute != null) {
var replaced = individual_lines[i].replace(/(\s(?:\w|=")+)-(\w)(\w+(:|=))/i, catenate);
stringArr.unshift(replaced);
} else {
stringArr.unshift(individual_lines[i] + '\n');
}
}
var updatedString = stringArr.join(''); // Recursion till all attributes have been concatinated
hasDashedAttributes(updatedString) ? findAttributedDashes(updatedString) : _this.string = updatedString;
} else {
_this.string = string;
}
};
findAttributedDashes(this.string); // Checks if inline style attributes not concatinated exist ex: style="font-size: 12px;" => style="fontSize: 12px;" ..
var catenateStyleAttribute = function catenateStyleAttribute(string) {
var replaced = string.replace(/(\sstyle="\w+)-(\w)(.*)/ig, catenate);
_this.string = replaced;
};
/**
* Format
* See {@link Format}
*/
var clientCopy = this.inlineStyleJSX(this.string, Format);
return {
renderedSVG: this.string,
forCopy: clientCopy
};
}
}]);
return Convert;
}();
module.exports = Convert;