diff options
Diffstat (limited to 'src/client/views/nodes/WebBoxRenderer.js')
-rw-r--r-- | src/client/views/nodes/WebBoxRenderer.js | 133 |
1 files changed, 61 insertions, 72 deletions
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js index 914adb404..6fb8f4957 100644 --- a/src/client/views/nodes/WebBoxRenderer.js +++ b/src/client/views/nodes/WebBoxRenderer.js @@ -1,3 +1,4 @@ +/* eslint-disable no-undef */ /** * * @param {StyleSheetList} styleSheets @@ -9,15 +10,14 @@ const ForeignHtmlRenderer = function (styleSheets) { * * @param {String} binStr */ - const binaryStringToBase64 = function (binStr) { - return new Promise(resolve => { + const binaryStringToBase64 = binStr => + new Promise(resolve => { const reader = new FileReader(); reader.readAsDataURL(binStr); reader.onloadend = function () { resolve(reader.result); }; }); - }; function prepend(extension) { return window.location.origin + extension; @@ -30,8 +30,8 @@ const ForeignHtmlRenderer = function (styleSheets) { * @param {String} url * @returns {Promise} */ - const getResourceAsBase64 = function (webUrl, inurl) { - return new Promise((resolve, reject) => { + const getResourceAsBase64 = (webUrl, inurl) => + new Promise(resolve => { const xhr = new XMLHttpRequest(); // const url = inurl.startsWith("/") && !inurl.startsWith("//") ? webUrl + inurl : inurl; // const url = CorsProxy(inurl.startsWith("/") && !inurl.startsWith("//") ? webUrl + inurl : inurl);// inurl.startsWith("http") ? CorsProxy(inurl) : inurl; @@ -67,16 +67,15 @@ const ForeignHtmlRenderer = function (styleSheets) { xhr.send(null); }); - }; /** * * @param {String[]} urls * @returns {Promise} */ - const getMultipleResourcesAsBase64 = function (webUrl, urls) { + const getMultipleResourcesAsBase64 = (webUrl, urls) => { const promises = []; - for (let i = 0; i < urls.length; i += 1) { + for (let i = 0; webUrl && i < urls.length; i += 1) { promises.push(getResourceAsBase64(webUrl, urls[i])); } return Promise.all(promises); @@ -130,6 +129,7 @@ const ForeignHtmlRenderer = function (styleSheets) { const urlsFound = []; let searchStartIndex = 0; + // eslint-disable-next-line no-constant-condition while (true) { const url = parseValue(cssRuleStr, searchStartIndex, selector, delimiters); if (url === null) { @@ -155,9 +155,6 @@ const ForeignHtmlRenderer = function (styleSheets) { const getImageUrlsFromFromHtml = function (html) { return getUrlsFromCssString(html, 'src=', [' ', '>', '\t'], true); }; - const getSourceUrlsFromFromHtml = function (html) { - return getUrlsFromCssString(html, 'source=', [' ', '>', '\t'], true); - }; const escapeRegExp = function (string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string @@ -171,46 +168,45 @@ const ForeignHtmlRenderer = function (styleSheets) { * * @returns {Promise<String>} */ - const buildSvgDataUri = async function (webUrl, inputContentHtml, width, height, scroll, xoff) { - return new Promise(async (resolve, reject) => { - /* !! The problems !! - * 1. CORS (not really an issue, expect perhaps for images, as this is a general security consideration to begin with) - * 2. Platform won't wait for external assets to load (fonts, images, etc.) - */ - - // copy styles - let cssStyles = ''; - const urlsFoundInCss = []; - - for (let i = 0; i < styleSheets.length; i += 1) { - try { - const rules = styleSheets[i].cssRules; - for (let j = 0; j < rules.length; j += 1) { - const cssRuleStr = rules[j].cssText; - urlsFoundInCss.push(...getUrlsFromCssString(cssRuleStr)); - cssStyles += cssRuleStr; - } - } catch (e) { - /* empty */ + const buildSvgDataUri = (webUrl, inputContentHtml, width, height, scroll, xoff) => { + /* !! The problems !! + * 1. CORS (not really an issue, expect perhaps for images, as this is a general security consideration to begin with) + * 2. Platform won't wait for external assets to load (fonts, images, etc.) + */ + + // copy styles + let cssStyles = ''; + const urlsFoundInCss = []; + + for (let i = 0; i < styleSheets.length; i += 1) { + try { + const rules = styleSheets[i].cssRules; + for (let j = 0; j < rules.length; j += 1) { + const cssRuleStr = rules[j].cssText; + urlsFoundInCss.push(...getUrlsFromCssString(cssRuleStr)); + cssStyles += cssRuleStr; } + } catch (e) { + /* empty */ } + } - // const fetchedResourcesFromStylesheets = await getMultipleResourcesAsBase64(webUrl, urlsFoundInCss); - // for (let i = 0; i < fetchedResourcesFromStylesheets.length; i++) { - // const r = fetchedResourcesFromStylesheets[i]; - // if (r.resourceUrl) { - // cssStyles = cssStyles.replace(new RegExp(escapeRegExp(r.resourceUrl), "g"), r.resourceBase64); - // } - // } - - let contentHtml = inputContentHtml - .replace(/<source[^>]*>/g, '') // <picture> tags have a <source> which has a srcset field of image refs. instead of converting each, just use the default <img> of the picture - .replace(/noscript/g, 'div') - .replace(/<div class="mediaset"><\/div>/g, '') // when scripting isn't available (ie, rendering web pages here), <noscript> tags should become <div>'s. But for Brown CS, there's a layout problem if you leave the empty <mediaset> tag - .replace(/<link[^>]*>/g, '') // don't need to keep any linked style sheets because we've already processed all style sheets above - .replace(/srcset="([^ "]*)[^"]*"/g, 'src="$1"'); // instead of converting each item in the srcset to a data url, just convert the first one and use that - const urlsFoundInHtml = getImageUrlsFromFromHtml(contentHtml).filter(url => !url.startsWith('data:')); - const fetchedResources = webUrl ? await getMultipleResourcesAsBase64(webUrl, urlsFoundInHtml) : []; + // const fetchedResourcesFromStylesheets = await getMultipleResourcesAsBase64(webUrl, urlsFoundInCss); + // for (let i = 0; i < fetchedResourcesFromStylesheets.length; i++) { + // const r = fetchedResourcesFromStylesheets[i]; + // if (r.resourceUrl) { + // cssStyles = cssStyles.replace(new RegExp(escapeRegExp(r.resourceUrl), "g"), r.resourceBase64); + // } + // } + + let contentHtml = inputContentHtml + .replace(/<source[^>]*>/g, '') // <picture> tags have a <source> which has a srcset field of image refs. instead of converting each, just use the default <img> of the picture + .replace(/noscript/g, 'div') + .replace(/<div class="mediaset"><\/div>/g, '') // when scripting isn't available (ie, rendering web pages here), <noscript> tags should become <div>'s. But for Brown CS, there's a layout problem if you leave the empty <mediaset> tag + .replace(/<link[^>]*>/g, '') // don't need to keep any linked style sheets because we've already processed all style sheets above + .replace(/srcset="([^ "]*)[^"]*"/g, 'src="$1"'); // instead of converting each item in the srcset to a data url, just convert the first one and use that + const urlsFoundInHtml = getImageUrlsFromFromHtml(contentHtml).filter(url => !url.startsWith('data:')); + return getMultipleResourcesAsBase64(webUrl, urlsFoundInHtml).then(fetchedResources => { for (let i = 0; i < fetchedResources.length; i += 1) { const r = fetchedResources[i]; if (r.resourceUrl) { @@ -243,9 +239,7 @@ const ForeignHtmlRenderer = function (styleSheets) { </svg>`; // convert SVG to data-uri - const dataUri = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svg)))}`; - - resolve(dataUri); + return `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svg)))}`; }); }; @@ -256,18 +250,19 @@ const ForeignHtmlRenderer = function (styleSheets) { * * @return {Promise<Image>} */ - this.renderToImage = async function (webUrl, html, width, height, scroll, xoff) { - return new Promise(async (resolve, reject) => { + this.renderToImage = (webUrl, html, width, height, scroll, xoff) => + new Promise(resolve => { const img = new Image(); - console.log(`BUILDING SVG for: ${webUrl}`); - img.src = await buildSvgDataUri(webUrl, html, width, height, scroll, xoff); - img.onload = function () { console.log(`IMAGE SVG created: ${webUrl}`); resolve(img); }; + console.log(`BUILDING SVG for: ${webUrl}`); + buildSvgDataUri(webUrl, html, width, height, scroll, xoff).then(uri => { + img.src = uri; + return img; + }); }); - }; /** * @param {String} html @@ -276,20 +271,16 @@ const ForeignHtmlRenderer = function (styleSheets) { * * @return {Promise<Image>} */ - this.renderToCanvas = async function (webUrl, html, width, height, scroll, xoff, oversample) { - return new Promise(async (resolve, reject) => { - const img = await self.renderToImage(webUrl, html, width, height, scroll, xoff); - + this.renderToCanvas = (webUrl, html, width, height, scroll, xoff, oversample) => + self.renderToImage(webUrl, html, width, height, scroll, xoff).then(img => { const canvas = document.createElement('canvas'); canvas.width = img.width * oversample; canvas.height = img.height * oversample; const canvasCtx = canvas.getContext('2d'); canvasCtx.drawImage(img, 0, 0, img.width * oversample, img.height * oversample); - - resolve(canvas); + return canvas; }); - }; /** * @param {String} html @@ -298,12 +289,10 @@ const ForeignHtmlRenderer = function (styleSheets) { * * @return {Promise<String>} */ - this.renderToBase64Png = async function (webUrl, html, width, height, scroll, xoff, oversample) { - return new Promise(async (resolve, reject) => { - const canvas = await self.renderToCanvas(webUrl, html, width, height, scroll, xoff, oversample); - resolve(canvas.toDataURL('image/png')); - }); - }; + this.renderToBase64Png = (webUrl, html, width, height, scroll, xoff, oversample) => + self + .renderToCanvas(webUrl, html, width, height, scroll, xoff, oversample) // + .then(canvas => canvas.toDataURL('image/png')); }; export function CreateImage(webUrl, styleSheets, html, width, height, scroll, xoff = 0, oversample = 1) { @@ -379,11 +368,11 @@ const ClipboardUtils = new (function () { .then(result => { loadFile(result, callback); }) - .catch(error => { + .catch(() => { callback(null, 'Reading clipboard error.'); }); }) - .catch(error => { + .catch(() => { callback(null, 'Reading clipboard error.'); }); } else { |