Merge pull request #12726 from dannon/chart-download-overhaul

[21.09] Charts downloads fixes and enhancements.
This commit is contained in:
Marius van den Beek
2021-10-19 14:57:42 +02:00
committed by GitHub
5 changed files with 214 additions and 252 deletions
+3
View File
@@ -36,7 +36,9 @@
"decode-uri-component": "^0.2.0",
"deep-diff": "^1.0.2",
"deep-equal": "^2.0.5",
"dom-to-image": "^2.6.0",
"elkjs": "^0.6.2",
"file-saver": "^2.0.5",
"flush-promises": "^1.0.2",
"glob": "^7.1.6",
"handsontable": "^2.0.0",
@@ -51,6 +53,7 @@
"jquery-ui": "^1.12.1",
"jquery.complexify": "^0.5.2",
"jquery.cookie": "^1.4.1",
"jspdf": "^2.4.0",
"linkifyjs": "^2.1.9",
"markdown-it": "^11.0.0",
"markdown-it-regexp": "^0.4.0",
@@ -1,203 +1,41 @@
/** This class enables users to export/download a chart as PNG, SVG or PDF. */
/** PNG export */
import $ from "jquery";
import domtoimage from "dom-to-image";
import { saveAs } from "file-saver";
import { jsPDF } from "jspdf";
function createPNG(options) {
if (options.$el.find("svg").length > 0) {
_svg2png(options);
} else {
_canvas2png(options);
}
}
function _downloadData(imageData, filename) {
const link = document.createElement("a");
link.download = filename;
link.href = imageData;
link.click();
}
function _downloadPNGData(imageData, filename) {
_downloadData(imageData.replace("image/png", "image/octet-stream"), `${filename || "GalaxyImage"}.png`);
}
function _toImage($el, x_offset, y_offset, newContext) {
var tagname = $el.prop("tagName").toLowerCase();
var p = $el.position();
var left =
x_offset +
p.left +
parseInt($el.css("marginLeft"), 10) +
parseInt($el.css("borderLeftWidth"), 10) +
parseInt($el.css("paddingLeft"), 10);
var top =
y_offset +
p.top +
parseInt($el.css("marginTop"), 10) +
parseInt($el.css("borderTopWidth"), 10) +
parseInt($el.css("paddingTop"), 10);
if (tagname == "div" || tagname == "span") {
$el.children().each(function () {
_toImage($(this), left, top);
});
} else if (tagname == "canvas") {
newContext.drawImage($el[0], left, top);
}
}
/** Convert canvas to png */
function _canvas2png(options) {
const $canvas = options.$el.find(".charts-viewer-canvas");
try {
if ($canvas.width() !== 0 && $canvas.height() !== 0) {
var newCanvas = document.createElement("canvas");
newCanvas.width = $canvas.outerWidth(true);
newCanvas.height = $canvas.outerHeight(true);
var newContext = newCanvas.getContext("2d");
newContext.save();
newContext.fillStyle = "rgb(255,255,255)";
newContext.fillRect(0, 0, newCanvas.width, newCanvas.height);
newContext.restore();
newContext.translate(0, 0);
newContext.textAlign = "left";
newContext.textBaseline = "top";
$canvas.children().each(function () {
_toImage($(this), 0, 0, newContext);
});
const imgData = newCanvas.toDataURL("image/png");
if (imgData) {
_downloadPNGData(imgData, options.title);
}
}
} catch (err) {
console.debug("FAILED - screenshot::_canvas2png() - " + err);
if (options.error) {
options.error("Please reduce your visualization to a single panel and try again.");
}
}
}
/** Convert svg to png */
function _svg2png(options) {
var scale = 5;
var xml = toXML(options);
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var source = new Image();
var $container = $('<div style="display:none;"/>').append($(canvas));
$("body").append($container);
canvas.width = xml.width * scale;
canvas.height = xml.height * scale;
source.src = "data:image/svg+xml;base64," + window.btoa(xml.string);
source.onload = function () {
context.drawImage(source, 0, 0, canvas.width, canvas.height);
const imageData = canvas.toDataURL("image/png");
_downloadPNGData(imageData, options.title);
$container.remove();
};
}
/** SVG export */
function createSVG(options) {
const imageData = `data:none/none;base64,${window.btoa(toXML(options).string)}`;
const filename = `${options.title || "GalaxyImage"}.svg`;
_downloadData(imageData, filename);
}
/** PDF export */
function createPDF(options) {
var xml = toXML(options);
var data = {
filename: "visualization",
type: "application/pdf",
height: xml.height,
width: xml.width,
scale: 2,
svg: xml.string,
};
var $el = $("body");
var form = $el.find("#viewer-form");
if (form.length === 0) {
form = $("<form>", {
id: "viewer-form",
method: "post",
action: "http://export.highcharts.com/",
display: "none",
});
$el.append(form);
}
form.empty();
for (var name in data) {
var input = $("<input/>", {
type: "hidden",
name: name,
value: data[name],
});
form.append(input);
}
try {
form.submit();
} catch (err) {
console.log(err);
}
}
/** XML export */
function toXML(options) {
var $svg = options.$el.find("svg");
if ($svg.length == 0) {
if (options.error) {
options.error("No SVG found. This visualization type does not support SVG/PDF export.");
return;
}
}
var nsvgs = $svg.length;
var height = parseInt($svg.first().css("height"));
var width = parseInt($svg.first().css("width"));
var serializer = new XMLSerializer();
var $composite = $("<svg/>").attr({
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
width: width * nsvgs,
height: height,
export function createPNG(options) {
domtoimage.toBlob(options.$el[0], { bgcolor: "#fff" }).then(function (blob) {
saveAs(blob, `${options.title || "my-chart"}.png`);
});
var offsetX = 0;
$svg.each(function () {
var $svg = $(this).clone();
_inline($svg);
var $g = $('<g transform="translate(' + offsetX + ', 0)">').attr("xmlns", "http://www.w3.org/2000/svg");
$g.append($svg.find("g").first());
$composite.append($g);
offsetX += width;
}
export function createSVG(options) {
domtoimage.toSvg(options.$el[0]).then(function (dataUrl) {
saveAs(dataUrl, `${options.title || "my-chart"}.svg`);
});
return {
string: serializer.serializeToString($composite[0]),
height: height,
width: width,
};
}
/** inlines CSS code */
function _inline($target) {
for (var sheet_id in document.styleSheets) {
var sheet = document.styleSheets[sheet_id];
var rules = sheet.cssRules;
if (rules) {
for (var idx = 0, len = rules.length; idx < len; idx++) {
try {
$target.find(rules[idx].selectorText).each(function (i, elem) {
elem.style.cssText += rules[idx].style.cssText;
});
} catch (err) {
console.error(err);
}
}
}
}
}
export function createPDF(options) {
domtoimage.toPng(options.$el[0]).then(function (dataUrl) {
const doc = new jsPDF();
// Calculate scaled image size. We want to leave a small margin, but
// fill the page width otherwise.
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
const elementWidth = options.$el.width();
const elementHeight = options.$el.height();
const scale = Math.min(pageWidth / elementWidth, pageHeight / elementHeight) * 0.95;
export default {
createPNG: createPNG,
createSVG: createSVG,
createPDF: createPDF,
};
doc.addImage(
dataUrl,
"png",
pageWidth * 0.025,
pageHeight * 0.025,
scale * elementWidth,
scale * elementHeight
);
doc.save(`${options.title || "my-chart"}.pdf`);
});
}
@@ -1,7 +1,6 @@
/** This class renders the chart menu options. */
import Backbone from "backbone";
import Ui from "mvc/ui/ui-misc";
import Screenshot from "mvc/visualization/chart/components/screenshot";
export default Backbone.View.extend({
initialize: function (app) {
@@ -24,13 +23,7 @@ export default Backbone.View.extend({
icon: "fa-file",
onclick: () => {
this._wait(app.chart, () => {
Screenshot.createPNG({
$el: app.viewer.$el,
title: app.chart.get("title"),
error: (err) => {
app.message.update({ message: err, status: "danger" });
},
});
this.downloadAs("png");
});
},
});
@@ -40,13 +33,7 @@ export default Backbone.View.extend({
icon: "fa-file-text-o",
onclick: () => {
this._wait(app.chart, () => {
Screenshot.createSVG({
$el: app.viewer.$el,
title: app.chart.get("title"),
error: (err) => {
app.message.update({ message: err, status: "danger" });
},
});
this.downloadAs("svg");
});
},
});
@@ -55,26 +42,8 @@ export default Backbone.View.extend({
title: "Save as PDF",
icon: "fa-file-o",
onclick: () => {
app.modal.show({
title: "Send visualization data for PDF creation",
body: "Galaxy does not provide integrated PDF export scripts. You may click 'Continue' to create the PDF by using a 3rd party service (https://export.highcharts.com).",
buttons: {
Cancel: () => {
app.modal.hide();
},
Continue: () => {
app.modal.hide();
this._wait(app.chart, () => {
Screenshot.createPDF({
$el: app.viewer.$el,
title: app.chart.get("title"),
error: (err) => {
app.message.update({ message: err, status: "danger" });
},
});
});
},
},
this._wait(app.chart, () => {
this.downloadAs("pdf");
});
},
});
@@ -130,6 +99,40 @@ export default Backbone.View.extend({
this.render();
},
downloadAs: function (filetype) {
import(/* webpackChunkName: "Screenshot" */ "mvc/visualization/chart/components/screenshot").then(
(Screenshot) => {
if (filetype === "png") {
Screenshot.createPNG({
$el: this.app.viewer.$el,
title: this.app.chart.get("title"),
error: (err) => {
this.app.message.update({ message: err, status: "danger" });
},
});
} else if (filetype === "svg") {
Screenshot.createSVG({
$el: this.app.viewer.$el,
title: this.app.chart.get("title"),
error: (err) => {
this.app.message.update({ message: err, status: "danger" });
},
});
} else if (filetype === "pdf") {
Screenshot.createPDF({
$el: this.app.viewer.$el,
title: this.app.chart.get("title"),
error: (err) => {
this.app.message.update({ message: err, status: "danger" });
},
});
} else {
this.app.message.update({ message: "Unknown artifact type.", status: "danger" });
}
}
);
},
render: function () {
var visible = this.model.get("visible");
this.app.$el[visible ? "removeClass" : "addClass"]("charts-fullscreen");
+1 -1
View File
@@ -53,7 +53,7 @@ module.exports = (env = {}, argv = {}) => {
},
libs: {
name: "libs",
test: /node_modules[\\/](?!(handsontable|pikaday|moment|elkjs)[\\/])|galaxy\/scripts\/libs/,
test: /node_modules[\\/](?!(jspdf|canvg|html2canvas|handsontable|pikaday|moment|elkjs)[\\/])|galaxy\/scripts\/libs/,
chunks: "all",
priority: -10,
},
+139 -21
View File
@@ -1115,10 +1115,10 @@
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.2":
version "7.11.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
dependencies:
regenerator-runtime "^0.13.4"
@@ -1988,6 +1988,11 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4"
integrity sha512-/rM+sWiuOZ5dvuVzV37sUuklsbg+JPOP8d+nNFlo2ZtfpzPiPvh1/gc8liWOLBqe+sR+ZM7guPaIcTt6UZTo7Q==
"@types/raf@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@types/raf/-/raf-3.4.0.tgz#2b72cbd55405e071f1c4d29992638e022b20acc2"
integrity sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==
"@types/source-list-map@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
@@ -3192,6 +3197,16 @@ base64-arraybuffer@0.1.5:
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
base64-arraybuffer@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45"
integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==
base64-arraybuffer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz#87bd13525626db4a9838e00a508c2b73efcf348c"
integrity sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==
base64-js@^1.0.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
@@ -3502,6 +3517,11 @@ bser@2.1.1:
dependencies:
node-int64 "^0.4.0"
btoa@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73"
integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==
buble@0.19.8:
version "0.19.8"
resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.8.tgz#d642f0081afab66dccd897d7b6360d94030b9d3d"
@@ -3749,6 +3769,20 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000890, caniuse-lite@^1.0.30000929, can
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001168.tgz"
integrity sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==
canvg@^3.0.6:
version "3.0.9"
resolved "https://registry.yarnpkg.com/canvg/-/canvg-3.0.9.tgz#9ba095f158b94b97ca2c9c1c40785b11dc08df6d"
integrity sha512-rDXcnRPuz4QHoCilMeoTxql+fvGqNAxp+qV/KHD8rOiJSAfVjFclbdUNHD2Uqfthr+VMg17bD2bVuk6F07oLGw==
dependencies:
"@babel/runtime" "^7.12.5"
"@types/raf" "^3.4.0"
core-js "^3.8.3"
raf "^3.4.1"
regenerator-runtime "^0.13.7"
rgbcolor "^1.0.1"
stackblur-canvas "^2.0.0"
svg-pathdata "^6.0.3"
capture-exit@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
@@ -4544,10 +4578,15 @@ core-js@^2.6.5:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
core-js@^3.6.0, core-js@^3.6.4:
version "3.6.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
core-js@^3.6.0, core-js@^3.8.3:
version "3.18.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509"
integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==
core-js@^3.6.4:
version "3.18.2"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.2.tgz#63a551e8a29f305cd4123754846e65896619ba5b"
integrity sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@@ -4649,6 +4688,13 @@ css-initials@^0.3.1:
resolved "https://registry.yarnpkg.com/css-initials/-/css-initials-0.3.1.tgz#0406d78e586fd12b9984a3f7d8a87fcbb2073208"
integrity sha512-fkshKv9vV8AmcxkAWVQ9DmEAKiqe09GHdnFaXecp0NIfsGnXIHVJAHfsxdRy9KXV0/KiWdjBqrCYto2fYIO4xQ==
css-line-break@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.0.1.tgz#3dc74c2ed5eb64211480281932475790243e7338"
integrity sha512-gwKYIMUn7xodIcb346wgUhE2Dt5O1Kmrc16PWi8sL4FTfyDj8P5095rzH7+O8CTZudJr+uw2GCI/hwEkDJFI2w==
dependencies:
base64-arraybuffer "^0.2.0"
css-loader@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea"
@@ -5284,6 +5330,11 @@ dom-serializer@0:
domelementtype "~1.1.1"
entities "~1.1.1"
dom-to-image@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867"
integrity sha1-ilA2CAiMh7HCL5A0rgMuGJiVWGc=
domain-browser@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
@@ -5306,6 +5357,11 @@ domexception@^2.0.1:
dependencies:
webidl-conversions "^5.0.0"
dompurify@^2.2.0:
version "2.3.3"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.3.tgz#c1af3eb88be47324432964d8abc75cf4b98d634c"
integrity sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==
domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
@@ -6253,6 +6309,11 @@ fetch-cookie@0.10.1:
dependencies:
tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0"
fflate@^0.4.8:
version "0.4.8"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
@@ -6280,6 +6341,11 @@ file-loader@^6.0.0:
loader-utils "^2.0.0"
schema-utils "^2.6.5"
file-saver@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@@ -6749,7 +6815,7 @@ glob-watcher@^5.0.3:
just-debounce "^1.0.0"
object.defaults "^1.1.0"
glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@@ -7189,6 +7255,14 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
html2canvas@^1.0.0-rc.5:
version "1.3.2"
resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.3.2.tgz#951cc8388a3ce939fdac02131007ee28124afc27"
integrity sha512-4+zqv87/a1LsaCrINV69wVLGG8GBZcYBboz1JPWEgiXcWoD9kroLzccsBRU/L9UlfV2MAZ+3J92U9IQPVMDeSQ==
dependencies:
css-line-break "2.0.1"
text-segmentation "^1.0.2"
http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
@@ -8892,6 +8966,21 @@ jsonify@~0.0.0:
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
jspdf@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/jspdf/-/jspdf-2.4.0.tgz#53d6d2acc63203b0b3688949597dd11a633b1db5"
integrity sha512-nsZ92YfbNG/EimR1yqmOkxf2D4iJRypBsw7pvP1aPiIEnoGITaLl6XDR/GYA36/R29vMZSBedpEhBCzutSGytA==
dependencies:
"@babel/runtime" "^7.14.0"
atob "^2.1.2"
btoa "^1.2.1"
fflate "^0.4.8"
optionalDependencies:
canvg "^3.0.6"
core-js "^3.6.0"
dompurify "^2.2.0"
html2canvas "^1.0.0-rc.5"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -12087,6 +12176,13 @@ qunit@^2.10.0:
node-watch "0.6.1"
resolve "1.9.0"
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
dependencies:
performance-now "^2.1.0"
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"
@@ -12526,10 +12622,10 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.13.4:
version "0.13.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
regenerator-transform@^0.14.2:
version "0.14.4"
@@ -12936,6 +13032,11 @@ rgba-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
rgbcolor@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/rgbcolor/-/rgbcolor-1.0.1.tgz#d6505ecdb304a6595da26fa4b43307306775945d"
integrity sha1-1lBezbMEplldom+ktDMHMGd1lF0=
right-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
@@ -12943,14 +13044,7 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
rimraf@^2.5.4:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
dependencies:
glob "^7.0.5"
rimraf@^2.6.3, rimraf@^2.7.1:
rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -13751,6 +13845,11 @@ stack-utils@^2.0.2:
dependencies:
escape-string-regexp "^2.0.0"
stackblur-canvas@^2.0.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz#aa87bbed1560fdcd3138fff344fc6a1c413ebac4"
integrity sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==
stackframe@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303"
@@ -14118,6 +14217,11 @@ sver-compat@^1.5.0:
es6-iterator "^2.0.1"
es6-symbol "^3.1.1"
svg-pathdata@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz#80b0e0283b652ccbafb69ad4f8f73e8d3fbf2cac"
integrity sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==
svgo@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985"
@@ -14252,6 +14356,13 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
text-segmentation@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.2.tgz#1f828fa14aa101c114ded1bda35ba7dcc17c9858"
integrity sha512-uTqvLxdBrVnx/CFQOtnf8tfzSXFm+1Qxau7Xi54j4OPTZokuDOX8qncQzrg2G8ZicAMOM8TgzFAYTb+AqNO4Cw==
dependencies:
utrie "^1.0.1"
text-table@0.2.0, text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -14928,6 +15039,13 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
utrie@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.1.tgz#e155235ebcbddc89ae09261ab6e773ce61401b2f"
integrity sha512-JPaDXF3vzgZxfeEwutdGzlrNoVFL5UvZcbO6Qo9D4GoahrieUPoMU8GCpVpR7MQqcKhmShIh8VlbEN3PLM3EBg==
dependencies:
base64-arraybuffer "^1.0.1"
uuid@8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"