fix(GUI): make archive-embedded svgs work again (#1642)

We make the svg-icon component accept XML in its path argument to handle
archive-embedded SVG icons.

Changelog-Entry: Make archive-embedded SVG icons work again.
Fixes: https://github.com/resin-io/etcher/issues/1636
This commit is contained in:
Benedict Aas 2017-08-01 17:34:06 +01:00 committed by Juan Cruz Viotti
parent a63b6bf18c
commit 7714e8b50a
4 changed files with 47 additions and 14 deletions

View File

@ -22,6 +22,7 @@
* @module Etcher.Components.SVGIcon
*/
const _ = require('lodash');
const angular = require('angular');
const react = require('react');
const propTypes = require('prop-types');
@ -53,13 +54,27 @@ class SVGIcon extends react.Component {
// relatively to the `index.html`.
const imagePath = path.join(__dirname, this.props.path);
const contents = fs.readFileSync(imagePath, {
encoding: 'utf8'
});
let contents = '';
if (_.startsWith(this.props.path, '<')) {
contents = this.props.path;
} else {
contents = fs.readFileSync(imagePath, {
encoding: 'utf8'
});
}
const width = this.props.width || DEFAULT_SIZE;
const height = this.props.height || DEFAULT_SIZE;
const parser = new DOMParser();
const doc = parser.parseFromString(contents, 'image/svg+xml');
const svg = doc.querySelector('svg');
const img = document.createElement('img');
img.src = `data:image/svg+xml,${encodeURIComponent(svg.outerHTML)}`;
return react.createElement('div', {
className: 'svg-icon',
height,
@ -70,7 +85,7 @@ class SVGIcon extends react.Component {
},
disabled: this.props.disabled,
dangerouslySetInnerHTML: {
__html: contents
__html: img.outerHTML
}
});
}

View File

@ -1,9 +1,9 @@
svg {
width: 100%;
height: 100%;
}
svg-icon {
display: inline-block;
img {
width: 100%;
height: 100%;
}
}

View File

@ -6413,12 +6413,11 @@ body {
.modal-drive-selector-modal .word-keep {
word-break: keep-all; }
svg {
width: 100%;
height: 100%; }
svg-icon {
display: inline-block; }
svg-icon img {
width: 100%;
height: 100%; }
/*
* Copyright 2016 resin.io

View File

@ -37,7 +37,26 @@ describe('Browser: SVGIcon', function() {
const element = $compile(`<svg-icon path="'${icon}'">Resin.io</svg-icon>`)($rootScope);
$rootScope.$digest();
m.chai.expect(element.children().html()).to.equal(iconContents);
// We parse the SVGs to get rid of discrepancies caused by string differences
// in the outputs; the XML trees are still equal, as proven here.
const originalSVGParser = new DOMParser();
const originalDoc = originalSVGParser.parseFromString(iconContents, 'image/svg+xml');
const compiledSVGParser = new DOMParser();
const compiledContents = decodeURIComponent(element.children()[0].children[0].src.substr(19));
const compiledDoc = compiledSVGParser.parseFromString(compiledContents, 'image/svg+xml');
m.chai.expect(compiledDoc.outerHTML).to.equal(originalDoc.outerHTML);
});
it('should accept an SVG in the path attribute', function() {
const iconContents = '<svg><rect x="10" y="10" height="100" width="100" style="stroke:red;fill:blue;"/></svg>';
const img = `<img src="data:image/svg+xml,${encodeURIComponent(iconContents)}">`;
$rootScope.iconContents = iconContents;
const element = $compile('<svg-icon path="iconContents">Resin.io</svg-icon>')($rootScope);
$rootScope.$digest();
m.chai.expect(element.children().html()).to.equal(img);
});
it('should default the size to 40x40 pixels', function() {