Simplify rendered SVGs slightly and add support for Safari
This commit is contained in:
parent
121830f69c
commit
01e43fd3eb
|
@ -4,14 +4,7 @@
|
||||||
<meta http-equiv="content-security-policy" content="
|
<meta http-equiv="content-security-policy" content="
|
||||||
base-uri 'self';
|
base-uri 'self';
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
script-src
|
script-src 'self' https://cdnjs.cloudflare.com;
|
||||||
'self'
|
|
||||||
'sha256-0SGl1PJNDyJwcV5T+weg2zpEMrh7xvlwO4oXgvZCeZk='
|
|
||||||
'sha256-eue5ceZRwKVQ1OXOZSyU7MXCTZMlqsPi/TOIqh1Vlzo='
|
|
||||||
'sha256-OvxDPyq6KQAoWh11DLJdBVlHHLkYYiy4EzqTjIEJbb4='
|
|
||||||
'sha256-vnm8bzrI+krtz5228JDC2DoTv0e+sfnfTCiUnO2EBAM='
|
|
||||||
'sha256-HYX1RusN7a369vYuOd1mGvxLcNL4z/MihkahAI2CH8k='
|
|
||||||
;
|
|
||||||
style-src 'self' https://cdnjs.cloudflare.com;
|
style-src 'self' https://cdnjs.cloudflare.com;
|
||||||
img-src 'self' blob:;
|
img-src 'self' blob:;
|
||||||
form-action 'none';
|
form-action 'none';
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
<meta http-equiv="content-security-policy" content="
|
<meta http-equiv="content-security-policy" content="
|
||||||
base-uri 'self';
|
base-uri 'self';
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
script-src
|
script-src 'self' https://cdnjs.cloudflare.com;
|
||||||
'self'
|
|
||||||
'sha256-0SGl1PJNDyJwcV5T+weg2zpEMrh7xvlwO4oXgvZCeZk='
|
|
||||||
;
|
|
||||||
style-src 'self';
|
style-src 'self';
|
||||||
connect-src 'self';
|
connect-src 'self';
|
||||||
img-src 'self' blob:;
|
img-src 'self' blob:;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
define(() => {
|
define(() => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Thanks, https://stackoverflow.com/a/23522755/1180785
|
||||||
|
const safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
return class Exporter {
|
return class Exporter {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.latestSVG = null;
|
this.latestSVG = null;
|
||||||
|
@ -41,11 +44,27 @@ define(() => {
|
||||||
const width = renderer.width * resolution;
|
const width = renderer.width * resolution;
|
||||||
const height = renderer.height * resolution;
|
const height = renderer.height * resolution;
|
||||||
const img = new Image(width, height);
|
const img = new Image(width, height);
|
||||||
|
let safariHackaround = null;
|
||||||
|
if(safari) {
|
||||||
|
// Safari fails to resize SVG images unless they are displayed
|
||||||
|
// on the page somewhere, so we must add it before drawing the
|
||||||
|
// image. For some reason, doing this inside the load listener
|
||||||
|
// is too late, so we do it here and do our best to ensure it
|
||||||
|
// doesn't change the page rendering (display:none fails too)
|
||||||
|
safariHackaround = document.createElement('div');
|
||||||
|
safariHackaround.style.position = 'absolute';
|
||||||
|
safariHackaround.style.visibility = 'hidden';
|
||||||
|
safariHackaround.appendChild(img);
|
||||||
|
document.body.appendChild(safariHackaround);
|
||||||
|
}
|
||||||
|
|
||||||
img.addEventListener('load', () => {
|
img.addEventListener('load', () => {
|
||||||
this.canvas.width = width;
|
this.canvas.width = width;
|
||||||
this.canvas.height = height;
|
this.canvas.height = height;
|
||||||
this.context.drawImage(img, 0, 0);
|
this.context.drawImage(img, 0, 0);
|
||||||
|
if(safariHackaround) {
|
||||||
|
document.body.removeChild(safariHackaround);
|
||||||
|
}
|
||||||
this.canvas.toBlob(callback, 'image/png');
|
this.canvas.toBlob(callback, 'image/png');
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
defineDescribe('Interface', ['./Interface'], (Interface) => {
|
defineDescribe('Interface', ['./Interface'], (Interface) => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Thanks, https://stackoverflow.com/a/23522755/1180785
|
||||||
|
const safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
let parser = null;
|
let parser = null;
|
||||||
let generator = null;
|
let generator = null;
|
||||||
let renderer = null;
|
let renderer = null;
|
||||||
|
@ -61,6 +64,11 @@ defineDescribe('Interface', ['./Interface'], (Interface) => {
|
||||||
ui.build(container);
|
ui.build(container);
|
||||||
|
|
||||||
expect(ui.downloadSVG.getAttribute('href')).toEqual('#');
|
expect(ui.downloadSVG.getAttribute('href')).toEqual('#');
|
||||||
|
if(safari) {
|
||||||
|
// Safari actually starts a download if we do this, which
|
||||||
|
// doesn't seem to fit its usual security vibe
|
||||||
|
return;
|
||||||
|
}
|
||||||
ui.downloadSVG.dispatchEvent(new Event('click'));
|
ui.downloadSVG.dispatchEvent(new Event('click'));
|
||||||
expect(ui.downloadSVG.getAttribute('href')).toEqual('mySVGURL');
|
expect(ui.downloadSVG.getAttribute('href')).toEqual('mySVGURL');
|
||||||
});
|
});
|
||||||
|
|
|
@ -126,10 +126,7 @@ define([
|
||||||
}
|
}
|
||||||
|
|
||||||
buildStaticElements() {
|
buildStaticElements() {
|
||||||
this.base = svg.makeContainer({
|
this.base = svg.makeContainer();
|
||||||
'width': '100%',
|
|
||||||
'height': '100%',
|
|
||||||
});
|
|
||||||
|
|
||||||
this.defs = svg.make('defs');
|
this.defs = svg.make('defs');
|
||||||
this.mask = svg.make('mask', {
|
this.mask = svg.make('mask', {
|
||||||
|
|
|
@ -47,7 +47,7 @@ defineDescribe('Sequence Integration', [
|
||||||
const sequence = generator.generate(parsed);
|
const sequence = generator.generate(parsed);
|
||||||
renderer.render(sequence);
|
renderer.render(sequence);
|
||||||
expect(getSimplifiedContent(renderer)).toEqual(
|
expect(getSimplifiedContent(renderer)).toEqual(
|
||||||
'<svg width="100%" height="100%" viewBox="-5 -5 10 10">' +
|
'<svg viewBox="-5 -5 10 10">' +
|
||||||
'<defs>' +
|
'<defs>' +
|
||||||
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
||||||
'<rect fill="#FFFFFF" x="-5" y="-5" width="10" height="10">' +
|
'<rect fill="#FFFFFF" x="-5" y="-5" width="10" height="10">' +
|
||||||
|
@ -65,7 +65,7 @@ defineDescribe('Sequence Integration', [
|
||||||
renderer.render(sequence);
|
renderer.render(sequence);
|
||||||
|
|
||||||
expect(getSimplifiedContent(renderer)).toEqual(
|
expect(getSimplifiedContent(renderer)).toEqual(
|
||||||
'<svg width="100%" height="100%" viewBox="-11.5 -16 23 21">' +
|
'<svg viewBox="-11.5 -16 23 21">' +
|
||||||
'<defs>' +
|
'<defs>' +
|
||||||
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
||||||
'<rect fill="#FFFFFF" x="-11.5" y="-16" width="23" height="21">' +
|
'<rect fill="#FFFFFF" x="-11.5" y="-16" width="23" height="21">' +
|
||||||
|
@ -92,7 +92,7 @@ defineDescribe('Sequence Integration', [
|
||||||
|
|
||||||
const content = getSimplifiedContent(renderer);
|
const content = getSimplifiedContent(renderer);
|
||||||
expect(content).toContain(
|
expect(content).toContain(
|
||||||
'<svg width="100%" height="100%" viewBox="-5 -5 82 47">'
|
'<svg viewBox="-5 -5 82 47">'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Agent 1
|
// Agent 1
|
||||||
|
|
|
@ -58,6 +58,11 @@ html, body {
|
||||||
.pane-view-inner {
|
.pane-view-inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pane-view svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.pane-error {
|
.pane-error {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
9
test.htm
9
test.htm
|
@ -4,14 +4,7 @@
|
||||||
<meta http-equiv="content-security-policy" content="
|
<meta http-equiv="content-security-policy" content="
|
||||||
base-uri 'self';
|
base-uri 'self';
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
script-src
|
script-src 'self' https://cdnjs.cloudflare.com;
|
||||||
'self'
|
|
||||||
'sha256-0SGl1PJNDyJwcV5T+weg2zpEMrh7xvlwO4oXgvZCeZk='
|
|
||||||
'sha256-nbDuV0lauU6Rzhc3T39vSmQ64+K0R8Kp556x6W5Xxg4='
|
|
||||||
'sha256-3t+j0EiiLhROsCHCLF+g/h4gPsyH5agBoZeAcOrydRM='
|
|
||||||
'sha256-Re9XxIL3x1flvE6WD58jWPdDzKYQLXwxS2HAVfmM6Z8='
|
|
||||||
'sha256-SYY59VkHlf1wmU3zhsnII/kb51ODoHy6ub8qaq0eAcY='
|
|
||||||
;
|
|
||||||
connect-src 'self';
|
connect-src 'self';
|
||||||
style-src 'self' https://cdnjs.cloudflare.com;
|
style-src 'self' https://cdnjs.cloudflare.com;
|
||||||
img-src 'self' data: blob:;
|
img-src 'self' data: blob:;
|
||||||
|
|
Loading…
Reference in New Issue