mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-23 19:26:33 +00:00
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:
parent
a63b6bf18c
commit
7714e8b50a
@ -22,6 +22,7 @@
|
|||||||
* @module Etcher.Components.SVGIcon
|
* @module Etcher.Components.SVGIcon
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
const angular = require('angular');
|
const angular = require('angular');
|
||||||
const react = require('react');
|
const react = require('react');
|
||||||
const propTypes = require('prop-types');
|
const propTypes = require('prop-types');
|
||||||
@ -53,13 +54,27 @@ class SVGIcon extends react.Component {
|
|||||||
// relatively to the `index.html`.
|
// relatively to the `index.html`.
|
||||||
const imagePath = path.join(__dirname, this.props.path);
|
const imagePath = path.join(__dirname, this.props.path);
|
||||||
|
|
||||||
const contents = fs.readFileSync(imagePath, {
|
let contents = '';
|
||||||
|
|
||||||
|
if (_.startsWith(this.props.path, '<')) {
|
||||||
|
contents = this.props.path;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
contents = fs.readFileSync(imagePath, {
|
||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const width = this.props.width || DEFAULT_SIZE;
|
const width = this.props.width || DEFAULT_SIZE;
|
||||||
const height = this.props.height || 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', {
|
return react.createElement('div', {
|
||||||
className: 'svg-icon',
|
className: 'svg-icon',
|
||||||
height,
|
height,
|
||||||
@ -70,7 +85,7 @@ class SVGIcon extends react.Component {
|
|||||||
},
|
},
|
||||||
disabled: this.props.disabled,
|
disabled: this.props.disabled,
|
||||||
dangerouslySetInnerHTML: {
|
dangerouslySetInnerHTML: {
|
||||||
__html: contents
|
__html: img.outerHTML
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg-icon {
|
svg-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6413,12 +6413,11 @@ body {
|
|||||||
.modal-drive-selector-modal .word-keep {
|
.modal-drive-selector-modal .word-keep {
|
||||||
word-break: keep-all; }
|
word-break: keep-all; }
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%; }
|
|
||||||
|
|
||||||
svg-icon {
|
svg-icon {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
|
svg-icon img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2016 resin.io
|
* Copyright 2016 resin.io
|
||||||
|
@ -37,7 +37,26 @@ describe('Browser: SVGIcon', function() {
|
|||||||
|
|
||||||
const element = $compile(`<svg-icon path="'${icon}'">Resin.io</svg-icon>`)($rootScope);
|
const element = $compile(`<svg-icon path="'${icon}'">Resin.io</svg-icon>`)($rootScope);
|
||||||
$rootScope.$digest();
|
$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() {
|
it('should default the size to 40x40 pixels', function() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user