Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svg-themer

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svg-themer - npm Package Compare versions

Comparing version 1.0.1 to 1.1.0

69

index.js

@@ -5,5 +5,12 @@ /* eslint-env browser */

var regexDataSvg64 = /^(data:image\/svg\+xml)(;\w+)?(,)(.*)$/;
var regexUrlDataSvg64 = /^(url\("data:image\/svg\+xml)(;\w+)?(,)(.*)("\))$/;
var ENCODING_MATCH_INDEX = 2, DATA_MATCH_INDEX = 4;
var PATTERN = '((data:image/svg\\+xml)(;\\w+)?(,)(.*)|(.*\\.svg))';
var regexDataSvg64 = new RegExp('^()' + PATTERN + '()$');
var regexUrlDataSvg64 = new RegExp('^(url\\(")' + PATTERN + '("\\))$');
var WHOLE_MATCH_INDEX = 0,
URL_CONSTRUCT_INDEX = 1,
URI_MATCH_INDEX = 2,
SCHEME_INDEX = 3,
ENCODING_MATCH_INDEX = 4,
DATA_MATCH_INDEX = 6,
SVG_FILE_URL_INDEX = 7;
var propsUsingImageUrl = ['background-image', 'list-style-image', 'border-image', 'content'];

@@ -29,3 +36,5 @@

if (match) {
this.src = applyThemeToSvg64.call(this, match, theme, setSvgProps);
applyThemeToSvgData.call(this, match, theme, setSvgProps, function(imageData) {
this.src = imageData;
});
}

@@ -52,7 +61,16 @@ }

} else {
propName = propsUsingImageUrl.find(matchProp);
// propName = propsUsingImageUrl.find(matchProp);
// avoiding .find() for IE11's sake
for (var i = 0; i < propsUsingImageUrl.length; ++i) {
propName = propsUsingImageUrl[i];
if (matchProp(propName)) {
break;
}
}
}
if (match) {
ruleProps[propName] = applyThemeToSvg64.call(this, match, theme, setSvgProps);
applyThemeToSvgData.call(this, match, theme, setSvgProps, function(urlImageData) {
ruleProps[propName] = urlImageData;
});
}

@@ -63,3 +81,32 @@

function applyThemeToSvg64(match, theme, setSvgProps) {
function applyThemeToSvgData(match, theme, setSvgProps, callback) {
var self = this;
if (match[SVG_FILE_URL_INDEX]) {
get(match[SVG_FILE_URL_INDEX], function(svgMarkup) {
match[SCHEME_INDEX] = 'data:image/svg+xml,';
match[DATA_MATCH_INDEX] = svgMarkup;
match[SVG_FILE_URL_INDEX] = '';
applyNow.call(self, match, theme, setSvgProps, callback);
});
} else {
applyNow.call(this, match, theme, setSvgProps, callback);
}
}
var HTTP_STATE_DONE = 4, HTTP_STATUS_OK = 200;
function get(url, callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = function() {
if (
httpRequest.readyState === HTTP_STATE_DONE &&
httpRequest.status === HTTP_STATUS_OK
) {
callback(httpRequest.responseText);
}
};
httpRequest.send(null);
}
function applyNow(match, theme, setSvgProps, callback) {
var encoding = match[ENCODING_MATCH_INDEX];

@@ -73,5 +120,6 @@ var data = match[DATA_MATCH_INDEX];

case undefined:
div.innerHTML = data;
div.innerHTML = data.indexOf('%3C') >= 0 ? decodeURIComponent(data) : data;
setSvgProps.call(div.firstElementChild, theme);
match[DATA_MATCH_INDEX] = div.firstElementChild.outerHTML;
var svgMarkup = (new XMLSerializer()).serializeToString(div.firstElementChild);
match[DATA_MATCH_INDEX] = encodeURIComponent(svgMarkup); // always encode result for IE11's sake
break;

@@ -88,3 +136,4 @@ case ';base64':

return match.slice(1).join('');
match[WHOLE_MATCH_INDEX] = match[URI_MATCH_INDEX] = undefined; // omit from join
callback.call(this, match.join(''));
}

@@ -91,0 +140,0 @@

7

package.json
{
"name": "svg-themer",
"version": "1.0.1",
"version": "1.1.0",
"description": "Apply a theme to SVG elements as well as image data and css rules constructed from SVG markup",

@@ -8,4 +8,5 @@ "main": "index.js",

"lint": "eslint -c ../fin-hypergrid/.eslintrc index.js",
"build": "mkdir umd; cp index.js umd/svg-themer.js; uglifyjs index.js > umd/svg-themer.min.js",
"test": "open test.html"
"build": "mkdir umd 2>/dev/null; cp index.js umd/svg-themer.js; uglifyjs index.js > umd/svg-themer.min.js; ls -lah umd/*.*",
"test": "http-server -p 49867 -o index.html # -o is not working for me",
"prepublishOnly": "npm run build"
},

@@ -12,0 +13,0 @@ "repository": {

@@ -15,2 +15,4 @@ # svg-themer

> **TL;DR** Skip to [API](#api) with examples.
SVG data is displayed on a web page by the following DOM `Element`s:

@@ -23,9 +25,18 @@ * `SVGSVGElement` — Represented in XML as `<svg>...</svg>` (with descendant elements)

The situation is quite different, however, for `<img/>` elements with underlying SVG data and for any element referencing SVG data via a CSS `url()` function. In these cases applying styles has _no effect_ on the image because it has already been rasterized.
The situation is quite different, however, for `<img/>` elements with underlying SVG data and for any element referencing SVG data via a CSS `url()` function. In these cases applying styles has _no effect_ on the image because it has already been rasterized. **With this module, you can apply a set of thematic styles directly to such SVG data.**
**With this module, you can apply a set of thematic styles directly to such SVG data.**
## Data encoding
This module properly handles all flavors of SVG data:
Entity | SVG Data Source | Example
------ | --------------- | -------
`HTMLImageElement` object | GET request | `<img src="yourfile.svg">`
`HTMLImageElement` object | in-line, raw (unencoded) | `<img src="data:image/svg+xml,...">`
`HTMLImageElement` object | in-line, base64-encoded | `<img src="data:image/svg+xml;base64,...">`
`CSSStyleRule` property | GET request | `background-image: url(yourfile.svg)`
`CSSStyleRule` property | in-line, URI-encoded | `background-image: url(data:image/svg+xml,...)`
`CSSStyleRule` property | in-line, base64-encoded | `background-image: url(data:image/svg+xml;base64,...)`
> **IMPORTANT NOTE:** For this to work, the SVG data must be "baked-in" to the object using `data:image/svg+xml`; this version does not handle file URLs.
> **Note:** Data in CSS `url()` constructs must always be encoded. (FYI, base64 encoding produces shorter results.)
> **Data encoding:** This module properly handles both unencoded data (`data:image/svg+xml,` + raw SVG markup) as well as base64-encoded data (`data:image/svg+xml;base64,` + encoded string). If you experience any issues trying to use unencoded SVG markup directly (such as nested quotes), you can always encode it.
> **Note:** Some browsers (looking at you, IE11) require `HTMLImageElement#src` to be encoded as well, depending on the content. For this reason, formerly unencoded data is always URI-encoded on write-back to `src` after styling as the content is now indeterminate.

@@ -58,4 +69,4 @@ ## `theme` objects

```html
<script src="https://unpkg.com/svg-themer@1.0/umd/svg-themer.js"></script>
<script src="https://unpkg.com/svg-themer@1.0/umd/svg-themer.min.js"></script>
<script src="https://unpkg.com/svg-themer/umd/svg-themer.js"></script>
<script src="https://unpkg.com/svg-themer/umd/svg-themer.min.js"></script>
```

@@ -143,3 +154,3 @@

```js
var rule = document.querySelector('style').sheet.rules[0]; // first rule in first stylesheet
var rule = document.querySelector('style').sheet.cssRules[0]; // first rule in first stylesheet
svgThemer.setRuleSvgProps.call(rule, theme.stopSignage);

@@ -171,3 +182,3 @@ ```

var imgEl = document.querySelector('img');
var rule = document.querySelector('style').sheet.rules[0]; // first rule in first stylesheet
var rule = document.querySelector('style').sheet.cssRules[0]; // first rule in first stylesheet

@@ -196,1 +207,17 @@ svgThemer.mixin(svgEl, propSetter);

## UAT
Tested in the following browsers:
* macOS 10.13.6 (17G65)
* Chrome 70.0.3538.77
* Safari 12.0 (13606.2.11)
* Opera 56.0.3051.102
* Firefox 63.0.1
* Windows 10
* Chrome 70.0.3538.77
* Opera 56.0.3051.70
* Firefox 63.0.0.6865
* Edge 42.17134.1.0
* Internet Explorer 11.345.17134.0 (Update 11.0.90)
## Version History
See [releases](https://github.com/joneit/svg-themer/releases).

@@ -5,5 +5,12 @@ /* eslint-env browser */

var regexDataSvg64 = /^(data:image\/svg\+xml)(;\w+)?(,)(.*)$/;
var regexUrlDataSvg64 = /^(url\("data:image\/svg\+xml)(;\w+)?(,)(.*)("\))$/;
var ENCODING_MATCH_INDEX = 2, DATA_MATCH_INDEX = 4;
var PATTERN = '((data:image/svg\\+xml)(;\\w+)?(,)(.*)|(.*\\.svg))';
var regexDataSvg64 = new RegExp('^()' + PATTERN + '()$');
var regexUrlDataSvg64 = new RegExp('^(url\\(")' + PATTERN + '("\\))$');
var WHOLE_MATCH_INDEX = 0,
URL_CONSTRUCT_INDEX = 1,
URI_MATCH_INDEX = 2,
SCHEME_INDEX = 3,
ENCODING_MATCH_INDEX = 4,
DATA_MATCH_INDEX = 6,
SVG_FILE_URL_INDEX = 7;
var propsUsingImageUrl = ['background-image', 'list-style-image', 'border-image', 'content'];

@@ -29,3 +36,5 @@

if (match) {
this.src = applyThemeToSvg64.call(this, match, theme, setSvgProps);
applyThemeToSvgData.call(this, match, theme, setSvgProps, function(imageData) {
this.src = imageData;
});
}

@@ -52,7 +61,16 @@ }

} else {
propName = propsUsingImageUrl.find(matchProp);
// propName = propsUsingImageUrl.find(matchProp);
// avoiding .find() for IE11's sake
for (var i = 0; i < propsUsingImageUrl.length; ++i) {
propName = propsUsingImageUrl[i];
if (matchProp(propName)) {
break;
}
}
}
if (match) {
ruleProps[propName] = applyThemeToSvg64.call(this, match, theme, setSvgProps);
applyThemeToSvgData.call(this, match, theme, setSvgProps, function(urlImageData) {
ruleProps[propName] = urlImageData;
});
}

@@ -63,3 +81,32 @@

function applyThemeToSvg64(match, theme, setSvgProps) {
function applyThemeToSvgData(match, theme, setSvgProps, callback) {
var self = this;
if (match[SVG_FILE_URL_INDEX]) {
get(match[SVG_FILE_URL_INDEX], function(svgMarkup) {
match[SCHEME_INDEX] = 'data:image/svg+xml,';
match[DATA_MATCH_INDEX] = svgMarkup;
match[SVG_FILE_URL_INDEX] = '';
applyNow.call(self, match, theme, setSvgProps, callback);
});
} else {
applyNow.call(this, match, theme, setSvgProps, callback);
}
}
var HTTP_STATE_DONE = 4, HTTP_STATUS_OK = 200;
function get(url, callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = function() {
if (
httpRequest.readyState === HTTP_STATE_DONE &&
httpRequest.status === HTTP_STATUS_OK
) {
callback(httpRequest.responseText);
}
};
httpRequest.send(null);
}
function applyNow(match, theme, setSvgProps, callback) {
var encoding = match[ENCODING_MATCH_INDEX];

@@ -73,5 +120,6 @@ var data = match[DATA_MATCH_INDEX];

case undefined:
div.innerHTML = data;
div.innerHTML = data.indexOf('%3C') >= 0 ? decodeURIComponent(data) : data;
setSvgProps.call(div.firstElementChild, theme);
match[DATA_MATCH_INDEX] = div.firstElementChild.outerHTML;
var svgMarkup = (new XMLSerializer()).serializeToString(div.firstElementChild);
match[DATA_MATCH_INDEX] = encodeURIComponent(svgMarkup); // always encode result for IE11's sake
break;

@@ -88,3 +136,4 @@ case ';base64':

return match.slice(1).join('');
match[WHOLE_MATCH_INDEX] = match[URI_MATCH_INDEX] = undefined; // omit from join
callback.call(this, match.join(''));
}

@@ -91,0 +140,0 @@

@@ -1,1 +0,1 @@

"use strict";var regexDataSvg64=/^(data:image\/svg\+xml)(;\w+)?(,)(.*)$/;var regexUrlDataSvg64=/^(url\("data:image\/svg\+xml)(;\w+)?(,)(.*)("\))$/;var ENCODING_MATCH_INDEX=2,DATA_MATCH_INDEX=4;var propsUsingImageUrl=["background-image","list-style-image","border-image","content"];var api;if(typeof exports==="undefined"){window.svgThemer=api={}}else{api=exports}api.setSvgProps=function(theme){if(theme.color){this.style.stroke=this.style.color=theme.color}if(theme.backgroundColor){this.style.fill=theme.backgroundColor}};api.setImgSvgProps=function(theme,setSvgProps){if(this.tagName==="IMG"){var match=this.src.match(regexDataSvg64);if(match){this.src=applyThemeToSvg64.call(this,match,theme,setSvgProps)}}return this};api.setRuleSvgProps=function(theme,setSvgProps,propName){var match;var ruleProps=this.style;if(typeof setSvgProps==="string"){propName=setSvgProps;setSvgProps=undefined}function matchProp(propName){return match=ruleProps[propName].match(regexUrlDataSvg64)}if(propName){matchProp(propName)}else{propName=propsUsingImageUrl.find(matchProp)}if(match){ruleProps[propName]=applyThemeToSvg64.call(this,match,theme,setSvgProps)}return this};function applyThemeToSvg64(match,theme,setSvgProps){var encoding=match[ENCODING_MATCH_INDEX];var data=match[DATA_MATCH_INDEX];var div=document.createElement("div");setSvgProps=setSvgProps||this.setSvgProps||api.setSvgProps;switch(encoding){case undefined:div.innerHTML=data;setSvgProps.call(div.firstElementChild,theme);match[DATA_MATCH_INDEX]=div.firstElementChild.outerHTML;break;case";base64":div.innerHTML=atob(data);setSvgProps.call(div.firstElementChild,theme);var svgMarkup=(new XMLSerializer).serializeToString(div.firstElementChild);match[DATA_MATCH_INDEX]=btoa(svgMarkup);break;default:throw new TypeError('Unexpected encoding "'+encoding+'"')}return match.slice(1).join("")}api.mixin=function(svgOrImgOrRule,setSvgProps){if(svgOrImgOrRule.tagName==="svg"){if(setSvgProps){svgOrImgOrRule.setTheme=setSvgProps}else{Object.defineProperty(svgOrImgOrRule,"setTheme",{get:function(){return api.setSvgProps}})}}else if(svgOrImgOrRule.tagName==="IMG"){if(setSvgProps){svgOrImgOrRule.setSvgProps=setSvgProps}svgOrImgOrRule.setTheme=api.setImgSvgProps}else if(svgOrImgOrRule=="[object CSSStyleRule]"){if(setSvgProps){svgOrImgOrRule.setSvgProps=setSvgProps}svgOrImgOrRule.setTheme=api.setRuleSvgProps}return svgOrImgOrRule};
"use strict";var PATTERN="((data:image/svg\\+xml)(;\\w+)?(,)(.*)|(.*\\.svg))";var regexDataSvg64=new RegExp("^()"+PATTERN+"()$");var regexUrlDataSvg64=new RegExp('^(url\\(")'+PATTERN+'("\\))$');var WHOLE_MATCH_INDEX=0,URL_CONSTRUCT_INDEX=1,URI_MATCH_INDEX=2,SCHEME_INDEX=3,ENCODING_MATCH_INDEX=4,DATA_MATCH_INDEX=6,SVG_FILE_URL_INDEX=7;var propsUsingImageUrl=["background-image","list-style-image","border-image","content"];var api;if(typeof exports==="undefined"){window.svgThemer=api={}}else{api=exports}api.setSvgProps=function(theme){if(theme.color){this.style.stroke=this.style.color=theme.color}if(theme.backgroundColor){this.style.fill=theme.backgroundColor}};api.setImgSvgProps=function(theme,setSvgProps){if(this.tagName==="IMG"){var match=this.src.match(regexDataSvg64);if(match){applyThemeToSvgData.call(this,match,theme,setSvgProps,function(imageData){this.src=imageData})}}return this};api.setRuleSvgProps=function(theme,setSvgProps,propName){var match;var ruleProps=this.style;if(typeof setSvgProps==="string"){propName=setSvgProps;setSvgProps=undefined}function matchProp(propName){return match=ruleProps[propName].match(regexUrlDataSvg64)}if(propName){matchProp(propName)}else{for(var i=0;i<propsUsingImageUrl.length;++i){propName=propsUsingImageUrl[i];if(matchProp(propName)){break}}}if(match){applyThemeToSvgData.call(this,match,theme,setSvgProps,function(urlImageData){ruleProps[propName]=urlImageData})}return this};function applyThemeToSvgData(match,theme,setSvgProps,callback){var self=this;if(match[SVG_FILE_URL_INDEX]){get(match[SVG_FILE_URL_INDEX],function(svgMarkup){match[SCHEME_INDEX]="data:image/svg+xml,";match[DATA_MATCH_INDEX]=svgMarkup;match[SVG_FILE_URL_INDEX]="";applyNow.call(self,match,theme,setSvgProps,callback)})}else{applyNow.call(this,match,theme,setSvgProps,callback)}}var HTTP_STATE_DONE=4,HTTP_STATUS_OK=200;function get(url,callback){var httpRequest=new XMLHttpRequest;httpRequest.open("GET",url,true);httpRequest.onreadystatechange=function(){if(httpRequest.readyState===HTTP_STATE_DONE&&httpRequest.status===HTTP_STATUS_OK){callback(httpRequest.responseText)}};httpRequest.send(null)}function applyNow(match,theme,setSvgProps,callback){var encoding=match[ENCODING_MATCH_INDEX];var data=match[DATA_MATCH_INDEX];var div=document.createElement("div");setSvgProps=setSvgProps||this.setSvgProps||api.setSvgProps;switch(encoding){case undefined:div.innerHTML=data.indexOf("%3C")>=0?decodeURIComponent(data):data;setSvgProps.call(div.firstElementChild,theme);var svgMarkup=(new XMLSerializer).serializeToString(div.firstElementChild);match[DATA_MATCH_INDEX]=encodeURIComponent(svgMarkup);break;case";base64":div.innerHTML=atob(data);setSvgProps.call(div.firstElementChild,theme);var svgMarkup=(new XMLSerializer).serializeToString(div.firstElementChild);match[DATA_MATCH_INDEX]=btoa(svgMarkup);break;default:throw new TypeError('Unexpected encoding "'+encoding+'"')}match[WHOLE_MATCH_INDEX]=match[URI_MATCH_INDEX]=undefined;callback.call(this,match.join(""))}api.mixin=function(svgOrImgOrRule,setSvgProps){if(svgOrImgOrRule.tagName==="svg"){if(setSvgProps){svgOrImgOrRule.setTheme=setSvgProps}else{Object.defineProperty(svgOrImgOrRule,"setTheme",{get:function(){return api.setSvgProps}})}}else if(svgOrImgOrRule.tagName==="IMG"){if(setSvgProps){svgOrImgOrRule.setSvgProps=setSvgProps}svgOrImgOrRule.setTheme=api.setImgSvgProps}else if(svgOrImgOrRule=="[object CSSStyleRule]"){if(setSvgProps){svgOrImgOrRule.setSvgProps=setSvgProps}svgOrImgOrRule.setTheme=api.setRuleSvgProps}return svgOrImgOrRule};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc