From 8f9cfa970e8527c4b656b13ad79d5cb02cc2c8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Prunayre?= Date: Thu, 10 Oct 2024 11:00:52 +0200 Subject: [PATCH] Map / Save your map improvements (#8155) * Map / Save your map improvements * Save your map create ISO19115-3 records (and can create ISO19139) * Distribution panel / Add a map section * Fix icon for map resource type in facet and record view * Indexing / Set only one resource type for records categorized as a map (map was also categorized as dataset). A map is an ISO record with * presentation form = mapDigital * format:PDF = static map * format:OWS-C = interactive map Index change: * resourceType `map/interactive` is now `map-interactive` * resourceType `map/static` is now `map-static` * Map / Save your map / Generate map overview by default * Map / Save your map improvements / Translations. --- .../config/associated-panel/default.json | 53 ++ .../convert/fromOGCWMC-OR-OWSC.xsl | 633 ++++++++++++++++++ .../iso19115-3.2018/index-fields/index.xsl | 20 + .../iso19115-3.2018/layout/config-editor.xml | 18 +- .../OGCWMC-OR-OWSC-to-ISO19139.xsl | 86 +-- .../OGCWMCtoISO19139/identification.xsl | 49 +- .../plugin/iso19139/index-fields/index.xsl | 28 +- .../api/records/MetadataInsertDeleteApi.java | 17 +- .../WEB-INF/classes/web-ui-wro-sources.xml | 2 - .../components/viewer/ViewerDirective.js | 2 +- .../viewer/owscontext/OwsContextDirective.js | 73 +- .../SearchLayerForMapDirective.js | 2 +- .../resources/catalog/js/CatController.js | 3 +- .../lib/dom-to-image/dom-to-image.min.js | 2 - .../resources/catalog/locales/en-editor.json | 3 + .../resources/catalog/style/gn_icons.less | 8 +- .../resources/catalog/views/default/module.js | 2 +- .../webapp/xslt/base-layout-cssjs-loader.xsl | 1 - 18 files changed, 854 insertions(+), 148 deletions(-) create mode 100644 schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/convert/fromOGCWMC-OR-OWSC.xsl delete mode 100644 web-ui/src/main/resources/catalog/lib/dom-to-image/dom-to-image.min.js diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/config/associated-panel/default.json b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/config/associated-panel/default.json index b37adf61088..8b05cb3f205 100644 --- a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/config/associated-panel/default.json +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/config/associated-panel/default.json @@ -799,6 +799,59 @@ } } }, + { + "group": "onlineUseMap", + "label": "map-interactive", + "copyLabel": "name", + "sources": { + "filestore": true + }, + "fileStoreFilter": "*.{xml,XML}", + "icon": "fa fa-map", + "process": "onlinesrc-add", + "fields": { + "url": { + "isMultilingual": false + }, + "name": {}, + "function": { + "value": "browsing", + "hidden": true, + "isMultilingual": false + }, + "protocol": { + "value": "OGC:OWS-C", + "hidden": true, + "isMultilingual": false + } + } + }, + { + "group": "onlineUseMap", + "label": "map-static", + "copyLabel": "name", + "sources": { + "filestore": true + }, + "fileStoreFilter": "*.{pdf,PDF}", + "icon": "fa fa-map", + "process": "onlinesrc-add", + "fields": { + "url": { + "isMultilingual": false + }, + "name": {}, + "function": { + "value": "browsing", + "hidden": true, + "isMultilingual": false + }, + "protocol": { + "value": "PDF:MAP", + "isMultilingual": false + } + } + }, { "group": "onlineUseLegend", "label": "onlineUseLegendLYR", diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/convert/fromOGCWMC-OR-OWSC.xsl b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/convert/fromOGCWMC-OR-OWSC.xsl new file mode 100644 index 00000000000..d3ccc7c62b1 --- /dev/null +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/convert/fromOGCWMC-OR-OWSC.xsl @@ -0,0 +1,633 @@ + + + + + eng + + + + + + + + + + + + + + + + [Y0001]-[M01]-[D01]T[H01]:[m01]:[s01] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + map + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ISO 19115-3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OGC:OWS-C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WWW:LINK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl index 9d67f38bac0..f73136cc9e0 100644 --- a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl @@ -240,11 +240,31 @@ and exists(mdb:contentInfo/*/mrc:featureCatalogue)" as="xs:boolean"/> + + + + + featureCatalog + + + + map-static + + + map-interactive + + + dataset diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/layout/config-editor.xml b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/layout/config-editor.xml index 9562c719939..e017378389d 100644 --- a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/layout/config-editor.xml +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/layout/config-editor.xml @@ -640,13 +640,17 @@ title: 'download', filter: 'protocol:OGC:WFS|OGC:WCS|.*DOWNLOAD.*|DB:.*|FILE:.*|OGC API Features|OGC API Coverages', editActions: ['addOnlinesrc#onlineDownload|localNetwork'] + }, { + title: 'map', + filter: 'protocol:OGC:OWS-C|PDF:MAP', + editActions: ['addOnlinesrc#onlineUseMap'] }, { title: 'mapLegend', filter: 'function:legend', editActions: ['addOnlinesrc#onlineUseLegend'] }, { title: 'links', - filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.* AND -function:legend|featureCatalogue|dataQualityReport', + filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.*|PDF:MAP AND -function:legend|featureCatalogue|dataQualityReport', editActions: ['addOnlinesrc#links'] }, { title: 'quality', @@ -743,13 +747,17 @@ title: 'download', filter: 'protocol:OGC:WFS|OGC:WCS|.*DOWNLOAD.*|DB:.*|FILE:.*|OGC API Features|OGC API Coverages', editActions: ['addOnlinesrc#onlineDownload|localNetwork'] + }, { + title: 'map', + filter: 'protocol:OGC:OWS-C|PDF:MAP', + editActions: ['addOnlinesrc#onlineUseMap'] }, { title: 'mapLegend', filter: 'function:legend', editActions: ['addOnlinesrc#onlineUseLegend'] }, { title: 'links', - filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.* AND -function:legend|featureCatalogue|dataQualityReport', + filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.*|PDF:MAP AND -function:legend|featureCatalogue|dataQualityReport', editActions: ['addOnlinesrc#links'] }, { title: 'quality', @@ -876,13 +884,17 @@ title: 'download', filter: 'protocol:OGC:WFS|OGC:WCS|.*DOWNLOAD.*|DB:.*|FILE:.*|OGC API Features|OGC API Coverages', editActions: ['addOnlinesrc#onlineDownload|localNetwork'] + }, { + title: 'map', + filter: 'protocol:OGC:OWS-C|PDF:MAP', + editActions: ['addOnlinesrc#onlineUseMap'] }, { title: 'mapLegend', filter: 'function:legend', editActions: ['addOnlinesrc#onlineUseLegend'] }, { title: 'links', - filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.* AND -function:legend|featureCatalogue|dataQualityReport', + filter:'-protocol:OGC.*|REST|ESRI:.*|atom.*|.*DOWNLOAD.*|DB:.*|FILE:.*|PDF:MAP AND -function:legend|featureCatalogue|dataQualityReport', editActions: ['addOnlinesrc#links'] }, { title: 'quality', diff --git a/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/OGCWMC-OR-OWSC-to-ISO19139.xsl b/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/OGCWMC-OR-OWSC-to-ISO19139.xsl index 9d5eb8d5384..6753f9c1f82 100644 --- a/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/OGCWMC-OR-OWSC-to-ISO19139.xsl +++ b/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/OGCWMC-OR-OWSC-to-ISO19139.xsl @@ -45,9 +45,8 @@ - - - + @@ -75,45 +74,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -318,4 +279,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/identification.xsl b/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/identification.xsl index 49a8f59750c..0e07348d910 100644 --- a/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/identification.xsl +++ b/schemas/iso19139/src/main/plugin/iso19139/convert/OGCWMCtoISO19139/identification.xsl @@ -22,7 +22,6 @@ ows-context:General/ows:Title"/> - @@ -70,50 +69,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - @@ -128,13 +87,11 @@ - - @@ -151,7 +108,5 @@ - - - + \ No newline at end of file diff --git a/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl b/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl index b38d4b12a0d..6f711e96804 100644 --- a/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl +++ b/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl @@ -192,19 +192,6 @@ - - - dataset - - - - - - - - - - - map - map/static + map-static - map/interactive + map-interactive + + dataset + + + + + + + + diff --git a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java index 8204995874d..ad25403313c 100644 --- a/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/MetadataInsertDeleteApi.java @@ -708,6 +708,9 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( @Parameter(description = "Publish record.", required = false) @RequestParam(required = false, defaultValue = "false") final boolean publishToAll, @Parameter(description = API_PARAM_RECORD_UUID_PROCESSING, required = false) @RequestParam(required = false, defaultValue = "NOTHING") final MEFLib.UuidAction uuidProcessing, @Parameter(description = API_PARAM_RECORD_GROUP, required = false) @RequestParam(required = false) final String group, + @Parameter(description = "Schema", required = false) + @RequestParam(required = false, defaultValue = "iso19139") + final String schema, HttpServletRequest request) throws Exception { if (StringUtils.isEmpty(xml) && StringUtils.isEmpty(url)) { throw new IllegalArgumentException("A context as XML or a remote URL MUST be provided."); @@ -718,12 +721,17 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( } ServiceContext context = ApiUtils.createServiceContext(request); - Path styleSheetWmc = dataDirectory.getXsltConversion("schema:iso19139:convert/fromOGCWMC-OR-OWSC"); + Path styleSheetWmc = dataDirectory.getXsltConversion( + String.format("schema:%s:convert/fromOGCWMC-OR-OWSC", + schema)); FilePathChecker.verify(filename); + String uuid = UUID.randomUUID().toString(); + // Convert the context in an ISO19139 records Map xslParams = new HashMap<>(); + xslParams.put("uuid", uuid); xslParams.put("viewer_url", viewerUrl); xslParams.put("map_url", url); xslParams.put("topic", topic); @@ -749,7 +757,6 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( // 4. Inserts the metadata (does basically the same as the metadata.insert.paste // service (see Insert.java) - String uuid = UUID.randomUUID().toString(); String date = new ISODate().toString(); SimpleMetadataProcessingReport report = new SimpleMetadataProcessingReport(); @@ -760,7 +767,7 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( md.add(transformedMd); // Import record - Importer.importRecord(uuid, uuidProcessing, md, "iso19139", 0, settingManager.getSiteId(), + Importer.importRecord(uuid, uuidProcessing, md, schema, 0, settingManager.getSiteId(), settingManager.getSiteName(), null, context, id, date, date, group, MetadataType.METADATA); final Store store = context.getBean("resourceStore", Store.class); @@ -779,7 +786,7 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( onlineSrcParams.put("name", filename); onlineSrcParams.put("desc", title); transformedMd = Xml.transform(transformedMd, - schemaManager.getSchemaDir("iso19139").resolve("process").resolve("onlinesrc-add.xsl"), + schemaManager.getSchemaDir(schema).resolve("process").resolve("onlinesrc-add.xsl"), onlineSrcParams); dataManager.updateMetadata(context, id.get(0), transformedMd, false, true, context.getLanguage(), null, true, IndexingMode.none); @@ -794,7 +801,7 @@ public SimpleMetadataProcessingReport insertOgcMapContextFile( onlineSrcParams.put("thumbnail_url", settingManager.getNodeURL() + String.format("api/records/%s/attachments/%s", uuid, overviewFilename)); transformedMd = Xml.transform(transformedMd, - schemaManager.getSchemaDir("iso19139").resolve("process").resolve("thumbnail-add.xsl"), + schemaManager.getSchemaDir(schema).resolve("process").resolve("thumbnail-add.xsl"), onlineSrcParams); dataManager.updateMetadata(context, id.get(0), transformedMd, false, true, context.getLanguage(), null, true, IndexingMode.none); diff --git a/web-ui/src/main/resources/WEB-INF/classes/web-ui-wro-sources.xml b/web-ui/src/main/resources/WEB-INF/classes/web-ui-wro-sources.xml index 3708d2bbf22..d65e5b19fd3 100644 --- a/web-ui/src/main/resources/WEB-INF/classes/web-ui-wro-sources.xml +++ b/web-ui/src/main/resources/WEB-INF/classes/web-ui-wro-sources.xml @@ -100,7 +100,6 @@ - @@ -174,6 +173,5 @@ - diff --git a/web-ui/src/main/resources/catalog/components/viewer/ViewerDirective.js b/web-ui/src/main/resources/catalog/components/viewer/ViewerDirective.js index 150d12bf1a4..b48ad9e2c40 100644 --- a/web-ui/src/main/resources/catalog/components/viewer/ViewerDirective.js +++ b/web-ui/src/main/resources/catalog/components/viewer/ViewerDirective.js @@ -408,7 +408,7 @@ filters: { filters: { maps: { - query_string: { query: '+resourceType:"map/interactive"' } + query_string: { query: '+resourceType:"map-interactive"' } } } } diff --git a/web-ui/src/main/resources/catalog/components/viewer/owscontext/OwsContextDirective.js b/web-ui/src/main/resources/catalog/components/viewer/owscontext/OwsContextDirective.js index c02aa5d8cac..edb386ea705 100644 --- a/web-ui/src/main/resources/catalog/components/viewer/owscontext/OwsContextDirective.js +++ b/web-ui/src/main/resources/catalog/components/viewer/owscontext/OwsContextDirective.js @@ -45,7 +45,7 @@ filters: [ { query_string: { - query: '+resourceType:"map/interactive"' + query: '+resourceType:"map-interactive"' } } ], @@ -140,27 +140,55 @@ scope.mapFileName = getMapFileName(); scope.map.once("postrender", function (event) { - domtoimage.toPng(scope.map.getTargetElement()).then(function (data) { - // resize if necessary - var finalData = data; - - if (scaleFactor !== undefined) { - var img = new Image(); - img.src = data; - img.onload = function () { - var canvas = document.createElement("canvas"); - var size = scope.map.getSize(); - canvas.width = size[0]; - canvas.height = size[1]; - canvas - .getContext("2d") - .drawImage(img, 0, 0, canvas.width, canvas.height); - finalData = canvas.toDataURL("image/png"); - }; + var mapCanvas = document.createElement("canvas"); + var size = scope.map.getSize(); + mapCanvas.width = size[0]; + mapCanvas.height = size[1]; + var mapContext = mapCanvas.getContext("2d"); + Array.prototype.forEach.call( + scope.map + .getViewport() + .querySelectorAll(".ol-layer canvas, canvas.ol-layer"), + function (canvas) { + if (canvas.width > 0) { + var opacity = + canvas.parentNode.style.opacity || canvas.style.opacity; + mapContext.globalAlpha = opacity === "" ? 1 : Number(opacity); + var matrix; + var transform = canvas.style.transform; + if (transform) { + // Get the transform parameters from the style's transform matrix + matrix = transform + .match(/^matrix\(([^\(]*)\)$/)[1] + .split(",") + .map(Number); + } else { + matrix = [ + parseFloat(canvas.style.width) / canvas.width, + 0, + 0, + parseFloat(canvas.style.height) / canvas.height, + 0, + 0 + ]; + } + // Apply the transform to the export map context + CanvasRenderingContext2D.prototype.setTransform.apply( + mapContext, + matrix + ); + var backgroundColor = canvas.parentNode.style.backgroundColor; + if (backgroundColor) { + mapContext.fillStyle = backgroundColor; + mapContext.fillRect(0, 0, canvas.width, canvas.height); + } + mapContext.drawImage(canvas, 0, 0); + } } - - defer.resolve(finalData); - }); + ); + mapContext.globalAlpha = 1; + mapContext.setTransform(1, 0, 0, 1, 0, 0); + defer.resolve(mapCanvas.toDataURL()); }); scope.map.renderSync(); } else { @@ -208,7 +236,8 @@ title: "", recordAbstract: "", group: null, - publishToAll: false + publishToAll: false, + schema: "iso19115-3.2018" }; scope.mapProps = angular.extend({}, defaultMapProps); diff --git a/web-ui/src/main/resources/catalog/components/viewer/searchlayerformap/SearchLayerForMapDirective.js b/web-ui/src/main/resources/catalog/components/viewer/searchlayerformap/SearchLayerForMapDirective.js index 7deaaa7c25b..ed4f17c7ea5 100644 --- a/web-ui/src/main/resources/catalog/components/viewer/searchlayerformap/SearchLayerForMapDirective.js +++ b/web-ui/src/main/resources/catalog/components/viewer/searchlayerformap/SearchLayerForMapDirective.js @@ -75,7 +75,7 @@ } }; if ($scope.mode === "map") { - $scope.searchObj.params.type = "map/interactive"; + $scope.searchObj.params.type = "map-interactive"; } else { $scope.searchObj.params.linkProtocol = "OGC:WMS*"; } diff --git a/web-ui/src/main/resources/catalog/js/CatController.js b/web-ui/src/main/resources/catalog/js/CatController.js index 79b66951b47..f9ae78f9e83 100644 --- a/web-ui/src/main/resources/catalog/js/CatController.js +++ b/web-ui/src/main/resources/catalog/js/CatController.js @@ -824,7 +824,7 @@ is3DModeAllowed: false, singleTileWMS: true, isSaveMapInCatalogAllowed: true, - isExportMapAsImageEnabled: false, + isExportMapAsImageEnabled: true, isAccessible: false, storage: "sessionStorage", bingKey: "", @@ -937,6 +937,7 @@ "protocol:OGC:WFS|OGC:WCS|.*DOWNLOAD.*|DB:.*|FILE:.*|OGC API Features|OGC API Coverages", title: "download" }, + { filter: "protocol:OGC:OWS-C", title: "map" }, { filter: "function:legend", title: "mapLegend" }, { filter: "function:featureCatalogue", diff --git a/web-ui/src/main/resources/catalog/lib/dom-to-image/dom-to-image.min.js b/web-ui/src/main/resources/catalog/lib/dom-to-image/dom-to-image.min.js deleted file mode 100644 index bc73227434d..00000000000 --- a/web-ui/src/main/resources/catalog/lib/dom-to-image/dom-to-image.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! dom-to-image 10-06-2017 */ -!function(a){"use strict";function b(a,b){function c(a){return b.bgcolor&&(a.style.backgroundColor=b.bgcolor),b.width&&(a.style.width=b.width+"px"),b.height&&(a.style.height=b.height+"px"),b.style&&Object.keys(b.style).forEach(function(c){a.style[c]=b.style[c]}),a}return b=b||{},g(b),Promise.resolve(a).then(function(a){return i(a,b.filter,!0)}).then(j).then(k).then(c).then(function(c){return l(c,b.width||q.width(a),b.height||q.height(a))})}function c(a,b){return h(a,b||{}).then(function(b){return b.getContext("2d").getImageData(0,0,q.width(a),q.height(a)).data})}function d(a,b){return h(a,b||{}).then(function(a){return a.toDataURL()})}function e(a,b){return b=b||{},h(a,b).then(function(a){return a.toDataURL("image/jpeg",b.quality||1)})}function f(a,b){return h(a,b||{}).then(q.canvasToBlob)}function g(a){"undefined"==typeof a.imagePlaceholder?v.impl.options.imagePlaceholder=u.imagePlaceholder:v.impl.options.imagePlaceholder=a.imagePlaceholder,"undefined"==typeof a.cacheBust?v.impl.options.cacheBust=u.cacheBust:v.impl.options.cacheBust=a.cacheBust}function h(a,c){function d(a){var b=document.createElement("canvas");if(b.width=c.width||q.width(a),b.height=c.height||q.height(a),c.bgcolor){var d=b.getContext("2d");d.fillStyle=c.bgcolor,d.fillRect(0,0,b.width,b.height)}return b}return b(a,c).then(q.makeImage).then(q.delay(100)).then(function(b){var c=d(a);return c.getContext("2d").drawImage(b,0,0),c})}function i(a,b,c){function d(a){return a instanceof HTMLCanvasElement?q.makeImage(a.toDataURL()):a.cloneNode(!1)}function e(a,b,c){function d(a,b,c){var d=Promise.resolve();return b.forEach(function(b){d=d.then(function(){return i(b,c)}).then(function(b){b&&a.appendChild(b)})}),d}var e=a.childNodes;return 0===e.length?Promise.resolve(b):d(b,q.asArray(e),c).then(function(){return b})}function f(a,b){function c(){function c(a,b){function c(a,b){q.asArray(a).forEach(function(c){b.setProperty(c,a.getPropertyValue(c),a.getPropertyPriority(c))})}a.cssText?b.cssText=a.cssText:c(a,b)}c(window.getComputedStyle(a),b.style)}function d(){function c(c){function d(a,b,c){function d(a){var b=a.getPropertyValue("content");return a.cssText+" content: "+b+";"}function e(a){function b(b){return b+": "+a.getPropertyValue(b)+(a.getPropertyPriority(b)?" !important":"")}return q.asArray(a).map(b).join("; ")+";"}var f="."+a+":"+b,g=c.cssText?d(c):e(c);return document.createTextNode(f+"{"+g+"}")}var e=window.getComputedStyle(a,c),f=e.getPropertyValue("content");if(""!==f&&"none"!==f){var g=q.uid();b.className=b.className+" "+g;var h=document.createElement("style");h.appendChild(d(g,c,e)),b.appendChild(h)}}[":before",":after"].forEach(function(a){c(a)})}function e(){a instanceof HTMLTextAreaElement&&(b.innerHTML=a.value),a instanceof HTMLInputElement&&b.setAttribute("value",a.value)}function f(){b instanceof SVGElement&&(b.setAttribute("xmlns","http://www.w3.org/2000/svg"),b instanceof SVGRectElement&&["width","height"].forEach(function(a){var c=b.getAttribute(a);c&&b.style.setProperty(a,c)}))}return b instanceof Element?Promise.resolve().then(c).then(d).then(e).then(f).then(function(){return b}):b}return c||!b||b(a)?Promise.resolve(a).then(d).then(function(c){return e(a,c,b)}).then(function(b){return f(a,b)}):Promise.resolve()}function j(a){return s.resolveAll().then(function(b){var c=document.createElement("style");return a.appendChild(c),c.appendChild(document.createTextNode(b)),a})}function k(a){return t.inlineAll(a).then(function(){return a})}function l(a,b,c){return Promise.resolve(a).then(function(a){return a.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(a)}).then(q.escapeXhtml).then(function(a){return''+a+""}).then(function(a){return''+a+""}).then(function(a){return"data:image/svg+xml;charset=utf-8,"+a})}function m(){function a(){var a="application/font-woff",b="image/jpeg";return{woff:a,woff2:a,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:b,jpeg:b,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml"}}function b(a){var b=/\.([^\.\/]*?)$/g.exec(a);return b?b[1]:""}function c(c){var d=b(c).toLowerCase();return a()[d]||""}function d(a){return a.search(/^(data:)/)!==-1}function e(a){return new Promise(function(b){for(var c=window.atob(a.toDataURL().split(",")[1]),d=c.length,e=new Uint8Array(d),f=0;f -