Last active
September 1, 2024 22:06
-
-
Save dcatanzaro/a5c4206fbf222a485ef5a006b2c3630f to your computer and use it in GitHub Desktop.
Revisions
-
dcatanzaro revised this gist
Sep 22, 2020 . 1 changed file with 12 additions and 531 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ //Twitter: https://twitter.com/DamianCatanzaro const html = "<html> \ <head> \ <style> \ @@ -27,537 +29,14 @@ const html = "<html> \ </body> \ </html>"; const js = `!function(t){"use strict";var g={parseExtension:function(t){return"png"},canvasToBlob:function(e){return e.toBlob?new Promise(function(t){e.toBlob(t)}):function(i){return new Promise(function(t){for(var e=window.atob(i.toDataURL().split(",")[1]),n=e.length,r=new Uint8Array(n),o=0;o<n;o++)r[o]=e.charCodeAt(o);t(new Blob([r],{type:"image/png"}))})}(e)},uid:function(){var t=0;return function(){return"u"+("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)+t++}}(),delay:function(n){return function(e){return new Promise(function(t){setTimeout(function(){t(e)},n)})}},asArray:function(t){for(var e=[],n=t.length,r=0;r<n;r++)e.push(t[r]);return e},escapeXhtml:function(t){return t},makeImage:function(r){return new Promise(function(t,e){var n=new Image;n.onload=function(){t(n)},n.onerror=e,n.src=r})},width:function(t){var e=r(t,"border-left-width"),n=r(t,"border-right-width");return t.scrollWidth+e+n},height:function(t){var e=r(t,"border-top-width"),n=r(t,"border-bottom-width");return t.scrollHeight+e+n}};function r(t,e){var n=window.getComputedStyle(t).getPropertyValue(e);return parseFloat(n.replace("px",""))}var e={imagePlaceholder:void 0,cacheBust:!1},n={toSvg:o,toBlob:function(t,e){return function(n,r){return o(n,r).then(g.makeImage).then(g.delay(100)).then(function(t){var e=function(t){var e=document.createElement("canvas");{var n;e.width=r.width||g.width(t),e.height=r.height||g.height(t),r.bgcolor&&((n=e.getContext("2d")).fillStyle=r.bgcolor,n.fillRect(0,0,e.width,e.height))}return e}(n);return e.getContext("2d").drawImage(t,0,0),e})}(t,e||{}).then(g.canvasToBlob)},impl:{options:{},util:g}};function o(o,i){return function(t){void 0===t.imagePlaceholder?n.impl.options.imagePlaceholder=e.imagePlaceholder:n.impl.options.imagePlaceholder=t.imagePlaceholder;void 0===t.cacheBust?n.impl.options.cacheBust=e.cacheBust:n.impl.options.cacheBust=t.cacheBust}(i=i||{}),Promise.resolve(o).then(function(t){return function i(e,n,t){if(!t&&n&&!n(e))return Promise.resolve();return Promise.resolve(e).then(r).then(function(t){return o(e,t,n)}).then(function(t){return u(e,t)});function r(t){return t instanceof HTMLCanvasElement?g.makeImage(t.toDataURL()):t.cloneNode(!1)}function o(t,e,n){var r=t.childNodes;return 0===r.length?Promise.resolve(e):o(e,g.asArray(r),n).then(function(){return e});function o(e,t,n){var r=Promise.resolve();return t.forEach(function(t){r=r.then(function(){return i(t,n)}).then(function(t){t&&e.appendChild(t)})}),r}}function u(f,d){return d instanceof Element?Promise.resolve().then(t).then(e).then(n).then(r).then(function(){return d}):d;function t(){function t(t,e){var n,r;t.cssText?e.cssText=t.cssText:(n=t,r=e,g.asArray(n).forEach(function(t){r.setProperty(t,n.getPropertyValue(t),n.getPropertyPriority(t))}))}t(window.getComputedStyle(f),d.style)}function e(){function e(t){var e,n,r,o,i,u,c,a,h=window.getComputedStyle(f,t),l=h.getPropertyValue("content");function s(t){return t+": "+r.getPropertyValue(t)+(r.getPropertyPriority(t)?" !important":"")}""!==l&&"none"!==l&&(e=g.uid(),d.className=d.className+" "+e,(n=document.createElement("style")).appendChild((c="."+e+":"+t,a=(u=h).cssText?(i=(o=o=u).getPropertyValue("content"),o.cssText+" content: "+i+";"):(r=u,g.asArray(r).map(s).join("; ")+";"),document.createTextNode(c+"{"+a+"}"))),d.appendChild(n))}[":before",":after"].forEach(function(t){e(t)})}function n(){f instanceof HTMLTextAreaElement&&(d.innerHTML=f.value),f instanceof HTMLInputElement&&d.setAttribute("value",f.value)}function r(){d instanceof SVGElement&&(d.setAttribute("xmlns","http://www.w3.org/2000/svg"),d instanceof SVGRectElement&&["width","height"].forEach(function(t){var e=d.getAttribute(t);e&&d.style.setProperty(t,e)}))}}}(t,i.filter,!0)}).then(function(e){i.bgcolor&&(e.style.backgroundColor=i.bgcolor);i.width&&(e.style.width=i.width+"px");i.height&&(e.style.height=i.height+"px");i.style&&Object.keys(i.style).forEach(function(t){e.style[t]=i.style[t]});return e}).then(function(t){return e=t,n=i.width||g.width(o),r=i.height||g.height(o),Promise.resolve(e).then(function(t){return t.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(t)}).then(g.escapeXhtml).then(function(t){return'<foreignObject x="0" y="0" width="100%" height="100%">'+t+"</foreignObject>"}).then(function(t){return'<svg xmlns="http://www.w3.org/2000/svg" width="'+n+'" height="'+r+'">'+t+"</svg>"}).then(function(t){return"data:image/svg+xml;charset=utf-8,"+t});var e,n,r})}"undefined"!=typeof module?module.exports=n:t.domtoimage=n}(this); const iframe = document.createElement("iframe"); document.body.appendChild(iframe); const iframedoc = iframe.contentDocument || iframe.contentWindow.document; iframedoc.body.innerHTML = "${html}"; const blobToBase64 = (blob) => { const reader = new FileReader(); reader.readAsDataURL(blob); @@ -567,18 +46,20 @@ const blobToBase64 = (blob) => { }; }); }; setTimeout(function () { domtoimage.toBlob(iframedoc.body).then(async (blob) => { completion(await blobToBase64(blob)); }); }, 1); `; const wv = new WebView(); const base64Image = await wv.evaluateJavaScript(js, true); const widget = new ListWidget(); const imgReqBq = await new Request(base64Image); const imgBq = await imgReqBq.loadImage(); widget.backgroundImage = imgBq; -
dcatanzaro revised this gist
Sep 22, 2020 . 1 changed file with 30 additions and 113 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,16 +1,42 @@ const html = "<html> \ <head> \ <style> \ body { \ margin: 0; \ background-color: cyan; \ width: 500px; \ height: 500px; \ } \ header { \ width: 100%; \ height: 100px; \ background-color: red; \ } \ .container { \ width: 100%; \ height: 400px; \ background-color: white; \ text-align: center; \ font-size: 50px; \ } \ </style> \ </head> \ <body> \ <header></header> \ <div class='container'>Widget construido con HTML y CSS, en iOS, si. En tu cara Jobs.</div> \ </body> \ </html>"; const js = `(function (global) { "use strict"; var util = newUtil(); // Default impl options var defaultOptions = { // Default is to fail on error, no placeholder imagePlaceholder: undefined, // Default cache bust is false, it will use the cache cacheBust: false, }; var domtoimage = { toSvg: toSvg, toPng: toPng, @@ -22,10 +48,8 @@ const js = `(function (global) { util: util, }, }; if (typeof module !== "undefined") module.exports = domtoimage; else global.domtoimage = domtoimage; /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options @@ -60,22 +84,17 @@ const js = `(function (global) { ); }) ); function applyOptions(clone) { if (options.bgcolor) clone.style.backgroundColor = options.bgcolor; if (options.width) clone.style.width = options.width + "px"; if (options.height) clone.style.height = options.height + "px"; if (options.style) Object.keys(options.style).forEach(function (property) { clone.style[property] = options.style[property]; }); return clone; } } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} @@ -88,7 +107,6 @@ const js = `(function (global) { .getImageData(0, 0, util.width(node), util.height(node)).data; }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} @@ -99,7 +117,6 @@ const js = `(function (global) { return canvas.toDataURL(); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} @@ -111,7 +128,6 @@ const js = `(function (global) { return canvas.toDataURL("image/jpeg", options.quality || 1.0); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} @@ -120,7 +136,6 @@ const js = `(function (global) { function toBlob(node, options) { return draw(node, options || {}).then(util.canvasToBlob); } function copyOptions(options) { // Copy options to impl options for use in impl if (typeof options.imagePlaceholder === "undefined") { @@ -129,14 +144,12 @@ const js = `(function (global) { } else { domtoimage.impl.options.imagePlaceholder = options.imagePlaceholder; } if (typeof options.cacheBust === "undefined") { domtoimage.impl.options.cacheBust = defaultOptions.cacheBust; } else { domtoimage.impl.options.cacheBust = options.cacheBust; } } function draw(domNode, options) { return toSvg(domNode, options) .then(util.makeImage) @@ -146,25 +159,20 @@ const js = `(function (global) { canvas.getContext("2d").drawImage(image, 0, 0); return canvas; }); function newCanvas(domNode) { var canvas = document.createElement("canvas"); canvas.width = options.width || util.width(domNode); canvas.height = options.height || util.height(domNode); if (options.bgcolor) { var ctx = canvas.getContext("2d"); ctx.fillStyle = options.bgcolor; ctx.fillRect(0, 0, canvas.width, canvas.height); } return canvas; } } function cloneNode(node, filter, root) { if (!root && filter && !filter(node)) return Promise.resolve(); return Promise.resolve(node) .then(makeNodeCopy) .then(function (clone) { @@ -173,25 +181,21 @@ const js = `(function (global) { .then(function (clone) { return processClone(node, clone); }); function makeNodeCopy(node) { if (node instanceof HTMLCanvasElement) return util.makeImage(node.toDataURL()); return node.cloneNode(false); } function cloneChildren(original, clone, filter) { var children = original.childNodes; if (children.length === 0) return Promise.resolve(clone); return cloneChildrenInOrder( clone, util.asArray(children), filter ).then(function () { return clone; }); function cloneChildrenInOrder(parent, children, filter) { var done = Promise.resolve(); children.forEach(function (child) { @@ -206,10 +210,8 @@ const js = `(function (global) { return done; } } function processClone(original, clone) { if (!(clone instanceof Element)) return clone; return Promise.resolve() .then(cloneStyle) .then(clonePseudoElements) @@ -218,14 +220,11 @@ const js = `(function (global) { .then(function () { return clone; }); function cloneStyle() { copyStyle(window.getComputedStyle(original), clone.style); function copyStyle(source, target) { if (source.cssText) target.cssText = source.cssText; else copyProperties(source, target); function copyProperties(source, target) { util.asArray(source).forEach(function (name) { target.setProperty( @@ -237,26 +236,21 @@ const js = `(function (global) { } } } function clonePseudoElements() { [":before", ":after"].forEach(function (element) { clonePseudoElement(element); }); function clonePseudoElement(element) { var style = window.getComputedStyle(original, element); var content = style.getPropertyValue("content"); if (content === "" || content === "none") return; var className = util.uid(); clone.className = clone.className + " " + className; var styleElement = document.createElement("style"); styleElement.appendChild( formatPseudoElementStyle(className, element, style) ); clone.appendChild(styleElement); function formatPseudoElementStyle( className, element, @@ -269,20 +263,17 @@ const js = `(function (global) { return document.createTextNode( selector + "{" + cssText + "}" ); function formatCssText(style) { var content = style.getPropertyValue("content"); return style.cssText + " content: " + content + ";"; } function formatCssProperties(style) { return ( util .asArray(style) .map(formatProperty) .join("; ") + ";" ); function formatProperty(name) { return ( name + @@ -297,29 +288,24 @@ const js = `(function (global) { } } } function copyUserInput() { if (original instanceof HTMLTextAreaElement) clone.innerHTML = original.value; if (original instanceof HTMLInputElement) clone.setAttribute("value", original.value); } function fixSvg() { if (!(clone instanceof SVGElement)) return; clone.setAttribute("xmlns", "http://www.w3.org/2000/svg"); if (!(clone instanceof SVGRectElement)) return; ["width", "height"].forEach(function (attribute) { var value = clone.getAttribute(attribute); if (!value) return; clone.style.setProperty(attribute, value); }); } } } function embedFonts(node) { return fontFaces.resolveAll().then(function (cssText) { var styleNode = document.createElement("style"); @@ -328,13 +314,11 @@ const js = `(function (global) { return node; }); } function inlineImages(node) { return images.inlineAll(node).then(function () { return node; }); } function makeSvgDataUri(node, width, height) { return Promise.resolve(node) .then(function (node) { @@ -364,7 +348,6 @@ const js = `(function (global) { return "data:image/svg+xml;charset=utf-8," + svg; }); } function newUtil() { return { escape: escape, @@ -383,15 +366,13 @@ const js = `(function (global) { width: width, height: height, }; function mimes() { /* * Only WOFF and EOT mime types for fonts are 'real' * see http://www.iana.org/assignments/media-types/media-types.xhtml */ var WOFF = "application/font-woff"; var JPEG = "image/jpeg"; return { woff: WOFF, woff2: WOFF, @@ -405,48 +386,39 @@ const js = `(function (global) { svg: "image/svg+xml", }; } function parseExtension(url) { return "png"; } function mimeType(url) { var extension = parseExtension(url).toLowerCase(); return mimes()[extension] || ""; } function isDataUrl(url) { return url.search(/^(data:)/) !== -1; } function toBlob(canvas) { return new Promise(function (resolve) { var binaryString = window.atob( canvas.toDataURL().split(",")[1] ); var length = binaryString.length; var binaryArray = new Uint8Array(length); for (var i = 0; i < length; i++) binaryArray[i] = binaryString.charCodeAt(i); resolve( new Blob([binaryArray], { type: "image/png", }) ); }); } function canvasToBlob(canvas) { if (canvas.toBlob) return new Promise(function (resolve) { canvas.toBlob(resolve); }); return toBlob(canvas); } function resolveUrl(url, baseUrl) { var doc = document.implementation.createHTMLDocument(); var base = doc.createElement("base"); @@ -457,13 +429,10 @@ const js = `(function (global) { a.href = url; return a.href; } function uid() { var index = 0; return function () { return "u" + fourRandomChars() + index++; function fourRandomChars() { /* see http://stackoverflow.com/a/6248722/2519373 */ return ( @@ -473,7 +442,6 @@ const js = `(function (global) { } }; } function makeImage(uri) { return new Promise(function (resolve, reject) { var image = new Image(); @@ -484,20 +452,16 @@ const js = `(function (global) { image.src = uri; }); } function getAndEncode(url) { var TIMEOUT = 30000; return new Promise(function (resolve) { var request = new XMLHttpRequest(); request.onreadystatechange = done; request.ontimeout = timeout; request.responseType = "blob"; request.timeout = TIMEOUT; request.open("GET", url, true); request.send(); var placeholder; if (domtoimage.impl.options.imagePlaceholder) { var split = domtoimage.impl.options.imagePlaceholder.split( @@ -507,10 +471,8 @@ const js = `(function (global) { placeholder = split[1]; } } function done() { if (request.readyState !== 4) return; if (request.status !== 200) { if (placeholder) { resolve(placeholder); @@ -522,18 +484,15 @@ const js = `(function (global) { request.status ); } return; } var encoder = new FileReader(); encoder.onloadend = function () { var content = encoder.result.split(/,/)[1]; resolve(content); }; encoder.readAsDataURL(request.response); } function timeout() { if (placeholder) { resolve(placeholder); @@ -546,22 +505,18 @@ const js = `(function (global) { ); } } function fail(message) { console.error(message); resolve(""); } }); } function dataAsUrl(content, type) { return "data:" + type + ";base64," + content; } function escape(string) { return ""; } function delay(ms) { return function (arg) { return new Promise(function (resolve) { @@ -571,30 +526,25 @@ const js = `(function (global) { }); }; } function asArray(arrayLike) { var array = []; var length = arrayLike.length; for (var i = 0; i < length; i++) array.push(arrayLike[i]); return array; } function escapeXhtml(string) { return string; } function width(node) { var leftBorder = px(node, "border-left-width"); var rightBorder = px(node, "border-right-width"); return node.scrollWidth + leftBorder + rightBorder; } function height(node) { var topBorder = px(node, "border-top-width"); var bottomBorder = px(node, "border-bottom-width"); return node.scrollHeight + topBorder + bottomBorder; } function px(node, styleProperty) { var value = window .getComputedStyle(node) @@ -604,41 +554,10 @@ const js = `(function (global) { } })(this); const iframe = document.createElement("iframe"); document.body.appendChild(iframe); const iframedoc = iframe.contentDocument || iframe.contentWindow.document; iframedoc.body.innerHTML = "${html}"; const blobToBase64 = (blob) => { const reader = new FileReader(); reader.readAsDataURL(blob); @@ -648,7 +567,6 @@ const blobToBase64 = (blob) => { }; }); }; setTimeout(function() { domtoimage.toBlob(iframedoc.body).then(async (blob) => { completion(await blobToBase64(blob)); @@ -657,7 +575,6 @@ setTimeout(function() { const wv = new WebView(); const test = await wv.evaluateJavaScript(js, true); const widget = new ListWidget(); -
dcatanzaro created this gist
Sep 22, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,674 @@ const js = `(function (global) { "use strict"; var util = newUtil(); // Default impl options var defaultOptions = { // Default is to fail on error, no placeholder imagePlaceholder: undefined, // Default cache bust is false, it will use the cache cacheBust: false, }; var domtoimage = { toSvg: toSvg, toPng: toPng, toJpeg: toJpeg, toBlob: toBlob, toPixelData: toPixelData, impl: { options: {}, util: util, }, }; if (typeof module !== "undefined") module.exports = domtoimage; else global.domtoimage = domtoimage; /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options * @param {Function} options.filter - Should return true if passed node should be included in the output * (excluding node means excluding it's children as well). Not called on the root node. * @param {String} options.bgcolor - color for the background, any valid CSS color value. * @param {Number} options.width - width to be applied to node before rendering. * @param {Number} options.height - height to be applied to node before rendering. * @param {Object} options.style - an object whose properties to be copied to node's style before rendering. * @param {Number} options.quality - a Number between 0 and 1 indicating image quality (applicable to JPEG only), defaults to 1.0. * @param {String} options.imagePlaceholder - dataURL to use as a placeholder for failed images, default behaviour is to fail fast on images we can't fetch * @param {Boolean} options.cacheBust - set to true to cache bust by appending the time to the request url * @return {Promise} - A promise that is fulfilled with a SVG image data URL * */ function toSvg(node, options) { options = options || {}; copyOptions(options); return ( Promise.resolve(node) .then(function (node) { return cloneNode(node, options.filter, true); }) //.then(embedFonts) //.then(inlineImages) .then(applyOptions) .then(function (clone) { return makeSvgDataUri( clone, options.width || util.width(node), options.height || util.height(node) ); }) ); function applyOptions(clone) { if (options.bgcolor) clone.style.backgroundColor = options.bgcolor; if (options.width) clone.style.width = options.width + "px"; if (options.height) clone.style.height = options.height + "px"; if (options.style) Object.keys(options.style).forEach(function (property) { clone.style[property] = options.style[property]; }); return clone; } } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} * @return {Promise} - A promise that is fulfilled with a Uint8Array containing RGBA pixel data. * */ function toPixelData(node, options) { return draw(node, options || {}).then(function (canvas) { return canvas .getContext("2d") .getImageData(0, 0, util.width(node), util.height(node)).data; }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} * @return {Promise} - A promise that is fulfilled with a PNG image data URL * */ function toPng(node, options) { return draw(node, options || {}).then(function (canvas) { return canvas.toDataURL(); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} * @return {Promise} - A promise that is fulfilled with a JPEG image data URL * */ function toJpeg(node, options) { options = options || {}; return draw(node, options).then(function (canvas) { return canvas.toDataURL("image/jpeg", options.quality || 1.0); }); } /** * @param {Node} node - The DOM Node object to render * @param {Object} options - Rendering options, @see {@link toSvg} * @return {Promise} - A promise that is fulfilled with a PNG image blob * */ function toBlob(node, options) { return draw(node, options || {}).then(util.canvasToBlob); } function copyOptions(options) { // Copy options to impl options for use in impl if (typeof options.imagePlaceholder === "undefined") { domtoimage.impl.options.imagePlaceholder = defaultOptions.imagePlaceholder; } else { domtoimage.impl.options.imagePlaceholder = options.imagePlaceholder; } if (typeof options.cacheBust === "undefined") { domtoimage.impl.options.cacheBust = defaultOptions.cacheBust; } else { domtoimage.impl.options.cacheBust = options.cacheBust; } } function draw(domNode, options) { return toSvg(domNode, options) .then(util.makeImage) .then(util.delay(100)) .then(function (image) { var canvas = newCanvas(domNode); canvas.getContext("2d").drawImage(image, 0, 0); return canvas; }); function newCanvas(domNode) { var canvas = document.createElement("canvas"); canvas.width = options.width || util.width(domNode); canvas.height = options.height || util.height(domNode); if (options.bgcolor) { var ctx = canvas.getContext("2d"); ctx.fillStyle = options.bgcolor; ctx.fillRect(0, 0, canvas.width, canvas.height); } return canvas; } } function cloneNode(node, filter, root) { if (!root && filter && !filter(node)) return Promise.resolve(); return Promise.resolve(node) .then(makeNodeCopy) .then(function (clone) { return cloneChildren(node, clone, filter); }) .then(function (clone) { return processClone(node, clone); }); function makeNodeCopy(node) { if (node instanceof HTMLCanvasElement) return util.makeImage(node.toDataURL()); return node.cloneNode(false); } function cloneChildren(original, clone, filter) { var children = original.childNodes; if (children.length === 0) return Promise.resolve(clone); return cloneChildrenInOrder( clone, util.asArray(children), filter ).then(function () { return clone; }); function cloneChildrenInOrder(parent, children, filter) { var done = Promise.resolve(); children.forEach(function (child) { done = done .then(function () { return cloneNode(child, filter); }) .then(function (childClone) { if (childClone) parent.appendChild(childClone); }); }); return done; } } function processClone(original, clone) { if (!(clone instanceof Element)) return clone; return Promise.resolve() .then(cloneStyle) .then(clonePseudoElements) .then(copyUserInput) .then(fixSvg) .then(function () { return clone; }); function cloneStyle() { copyStyle(window.getComputedStyle(original), clone.style); function copyStyle(source, target) { if (source.cssText) target.cssText = source.cssText; else copyProperties(source, target); function copyProperties(source, target) { util.asArray(source).forEach(function (name) { target.setProperty( name, source.getPropertyValue(name), source.getPropertyPriority(name) ); }); } } } function clonePseudoElements() { [":before", ":after"].forEach(function (element) { clonePseudoElement(element); }); function clonePseudoElement(element) { var style = window.getComputedStyle(original, element); var content = style.getPropertyValue("content"); if (content === "" || content === "none") return; var className = util.uid(); clone.className = clone.className + " " + className; var styleElement = document.createElement("style"); styleElement.appendChild( formatPseudoElementStyle(className, element, style) ); clone.appendChild(styleElement); function formatPseudoElementStyle( className, element, style ) { var selector = "." + className + ":" + element; var cssText = style.cssText ? formatCssText(style) : formatCssProperties(style); return document.createTextNode( selector + "{" + cssText + "}" ); function formatCssText(style) { var content = style.getPropertyValue("content"); return style.cssText + " content: " + content + ";"; } function formatCssProperties(style) { return ( util .asArray(style) .map(formatProperty) .join("; ") + ";" ); function formatProperty(name) { return ( name + ": " + style.getPropertyValue(name) + (style.getPropertyPriority(name) ? " !important" : "") ); } } } } } function copyUserInput() { if (original instanceof HTMLTextAreaElement) clone.innerHTML = original.value; if (original instanceof HTMLInputElement) clone.setAttribute("value", original.value); } function fixSvg() { if (!(clone instanceof SVGElement)) return; clone.setAttribute("xmlns", "http://www.w3.org/2000/svg"); if (!(clone instanceof SVGRectElement)) return; ["width", "height"].forEach(function (attribute) { var value = clone.getAttribute(attribute); if (!value) return; clone.style.setProperty(attribute, value); }); } } } function embedFonts(node) { return fontFaces.resolveAll().then(function (cssText) { var styleNode = document.createElement("style"); node.appendChild(styleNode); styleNode.appendChild(document.createTextNode(cssText)); return node; }); } function inlineImages(node) { return images.inlineAll(node).then(function () { return node; }); } function makeSvgDataUri(node, width, height) { return Promise.resolve(node) .then(function (node) { node.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); return new XMLSerializer().serializeToString(node); }) .then(util.escapeXhtml) .then(function (xhtml) { return ( '<foreignObject x="0" y="0" width="100%" height="100%">' + xhtml + "</foreignObject>" ); }) .then(function (foreignObject) { return ( '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '">' + foreignObject + "</svg>" ); }) .then(function (svg) { return "data:image/svg+xml;charset=utf-8," + svg; }); } function newUtil() { return { escape: escape, parseExtension: parseExtension, mimeType: mimeType, dataAsUrl: dataAsUrl, isDataUrl: isDataUrl, canvasToBlob: canvasToBlob, resolveUrl: resolveUrl, getAndEncode: getAndEncode, uid: uid(), delay: delay, asArray: asArray, escapeXhtml: escapeXhtml, makeImage: makeImage, width: width, height: height, }; function mimes() { /* * Only WOFF and EOT mime types for fonts are 'real' * see http://www.iana.org/assignments/media-types/media-types.xhtml */ var WOFF = "application/font-woff"; var JPEG = "image/jpeg"; return { woff: WOFF, woff2: WOFF, ttf: "application/font-truetype", eot: "application/vnd.ms-fontobject", png: "image/png", jpg: JPEG, jpeg: JPEG, gif: "image/gif", tiff: "image/tiff", svg: "image/svg+xml", }; } function parseExtension(url) { return "png"; } function mimeType(url) { var extension = parseExtension(url).toLowerCase(); return mimes()[extension] || ""; } function isDataUrl(url) { return url.search(/^(data:)/) !== -1; } function toBlob(canvas) { return new Promise(function (resolve) { var binaryString = window.atob( canvas.toDataURL().split(",")[1] ); var length = binaryString.length; var binaryArray = new Uint8Array(length); for (var i = 0; i < length; i++) binaryArray[i] = binaryString.charCodeAt(i); resolve( new Blob([binaryArray], { type: "image/png", }) ); }); } function canvasToBlob(canvas) { if (canvas.toBlob) return new Promise(function (resolve) { canvas.toBlob(resolve); }); return toBlob(canvas); } function resolveUrl(url, baseUrl) { var doc = document.implementation.createHTMLDocument(); var base = doc.createElement("base"); doc.head.appendChild(base); var a = doc.createElement("a"); doc.body.appendChild(a); base.href = baseUrl; a.href = url; return a.href; } function uid() { var index = 0; return function () { return "u" + fourRandomChars() + index++; function fourRandomChars() { /* see http://stackoverflow.com/a/6248722/2519373 */ return ( "0000" + ((Math.random() * Math.pow(36, 4)) << 0).toString(36) ).slice(-4); } }; } function makeImage(uri) { return new Promise(function (resolve, reject) { var image = new Image(); image.onload = function () { resolve(image); }; image.onerror = reject; image.src = uri; }); } function getAndEncode(url) { var TIMEOUT = 30000; return new Promise(function (resolve) { var request = new XMLHttpRequest(); request.onreadystatechange = done; request.ontimeout = timeout; request.responseType = "blob"; request.timeout = TIMEOUT; request.open("GET", url, true); request.send(); var placeholder; if (domtoimage.impl.options.imagePlaceholder) { var split = domtoimage.impl.options.imagePlaceholder.split( /,/ ); if (split && split[1]) { placeholder = split[1]; } } function done() { if (request.readyState !== 4) return; if (request.status !== 200) { if (placeholder) { resolve(placeholder); } else { fail( "cannot fetch resource: " + url + ", status: " + request.status ); } return; } var encoder = new FileReader(); encoder.onloadend = function () { var content = encoder.result.split(/,/)[1]; resolve(content); }; encoder.readAsDataURL(request.response); } function timeout() { if (placeholder) { resolve(placeholder); } else { fail( "timeout of " + TIMEOUT + "ms occured while fetching resource: " + url ); } } function fail(message) { console.error(message); resolve(""); } }); } function dataAsUrl(content, type) { return "data:" + type + ";base64," + content; } function escape(string) { return ""; } function delay(ms) { return function (arg) { return new Promise(function (resolve) { setTimeout(function () { resolve(arg); }, ms); }); }; } function asArray(arrayLike) { var array = []; var length = arrayLike.length; for (var i = 0; i < length; i++) array.push(arrayLike[i]); return array; } function escapeXhtml(string) { return string; } function width(node) { var leftBorder = px(node, "border-left-width"); var rightBorder = px(node, "border-right-width"); return node.scrollWidth + leftBorder + rightBorder; } function height(node) { var topBorder = px(node, "border-top-width"); var bottomBorder = px(node, "border-bottom-width"); return node.scrollHeight + topBorder + bottomBorder; } function px(node, styleProperty) { var value = window .getComputedStyle(node) .getPropertyValue(styleProperty); return parseFloat(value.replace("px", "")); } } })(this); const html = "<html> \ <head> \ <style> \ body { \ margin: 0; \ background-color: cyan; \ width: 500px; \ height: 500px; \ } \ header { \ width: 100%; \ height: 100px; \ background-color: red; \ } \ .container { \ width: 100%; \ height: 400px; \ background-color: white; \ text-align: center; \ font-size: 50px; \ } \ </style> \ </head> \ <body> \ <header></header> \ <div class='container'>Widget construido con HTML y CSS, en iOS, si. En tu cara Jobs.</div> \ </body> \ </html>"; const iframe = document.createElement("iframe"); document.body.appendChild(iframe); const iframedoc = iframe.contentDocument || iframe.contentWindow.document; iframedoc.body.innerHTML = html; const blobToBase64 = (blob) => { const reader = new FileReader(); reader.readAsDataURL(blob); return new Promise((resolve) => { reader.onloadend = () => { resolve(reader.result); }; }); }; setTimeout(function() { domtoimage.toBlob(iframedoc.body).then(async (blob) => { completion(await blobToBase64(blob)); }); }, 1)`; const wv = new WebView(); const test = await wv.evaluateJavaScript(js, true); log(test); const widget = new ListWidget(); const imgReqBq = await new Request(test); const imgBq = await imgReqBq.loadImage(); widget.backgroundImage = imgBq; if (config.runsInWidget) { Script.setWidget(widget); Script.complete(); } else { widget.presentLarge(); }