aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/WebBoxRenderer.js
diff options
context:
space:
mode:
authormehekj <mehek.jethani@gmail.com>2022-03-20 10:29:42 -0400
committermehekj <mehek.jethani@gmail.com>2022-03-20 10:29:42 -0400
commit0a5e02a87fdabff5ff8399829ff857cae90fc1e2 (patch)
treeb7c05080dac66366768f23e59a43f62533a22415 /src/client/views/nodes/WebBoxRenderer.js
parent1f7cf7babc76ecff5aef5fe663c48e067e85dd26 (diff)
Revert "Merge remote-tracking branch 'origin/speedups2' into temporalmedia-mehek"
This reverts commit 1f7cf7babc76ecff5aef5fe663c48e067e85dd26, reversing changes made to 1e3ad4de06f83eab54628de660529fefb9a0dc63.
Diffstat (limited to 'src/client/views/nodes/WebBoxRenderer.js')
-rw-r--r--src/client/views/nodes/WebBoxRenderer.js395
1 files changed, 0 insertions, 395 deletions
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js
deleted file mode 100644
index 08a5746d1..000000000
--- a/src/client/views/nodes/WebBoxRenderer.js
+++ /dev/null
@@ -1,395 +0,0 @@
-/**
- *
- * @param {StyleSheetList} styleSheets
- */
-var ForeignHtmlRenderer = function (styleSheets) {
-
- const self = this;
-
- /**
- *
- * @param {String} binStr
- */
- const binaryStringToBase64 = function (binStr) {
- return new Promise(function (resolve) {
- const reader = new FileReader();
- reader.readAsDataURL(binStr);
- reader.onloadend = function () {
- resolve(reader.result);
- }
- });
- };
-
- function prepend(extension) {
- return window.location.origin + extension;
- }
- function CorsProxy(url) {
- return prepend("/corsProxy/") + encodeURIComponent(url);
- }
- /**
- *
- * @param {String} url
- * @returns {Promise}
- */
- const getResourceAsBase64 = function (webUrl, inurl) {
- return new Promise(function (resolve, reject) {
- 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;
- var url = inurl;
- if (inurl.startsWith("/static")) {
- url = (new URL(webUrl).origin + inurl);
- } else
- if ((inurl.startsWith("/") && !inurl.startsWith("//"))) {
- url = CorsProxy(new URL(webUrl).origin + inurl);
- } else if (!inurl.startsWith("http") && !inurl.startsWith("//")) {
- url = CorsProxy(webUrl + "/" + inurl);
- }
- xhr.open("GET", url);
- xhr.responseType = 'blob';
-
- xhr.onreadystatechange = async function () {
- if (xhr.readyState === 4 && xhr.status === 200) {
- const resBase64 = await binaryStringToBase64(xhr.response);
-
- resolve(
- {
- "resourceUrl": inurl,
- "resourceBase64": resBase64
- }
- );
- } else if (xhr.readyState === 4) {
- console.log("COULDN'T FIND: " + (inurl.startsWith("/") ? webUrl + inurl : inurl));
- resolve(
- {
- "resourceUrl": "",
- "resourceBase64": inurl
- }
- );
- }
- };
-
- xhr.send(null);
- });
- };
-
- /**
- *
- * @param {String[]} urls
- * @returns {Promise}
- */
- const getMultipleResourcesAsBase64 = function (webUrl, urls) {
- const promises = [];
- for (let i = 0; i < urls.length; i++) {
- promises.push(getResourceAsBase64(webUrl, urls[i]));
- }
- return Promise.all(promises);
- };
-
- /**
- *
- * @param {String} str
- * @param {Number} startIndex
- * @param {String} prefixToken
- * @param {String[]} suffixTokens
- *
- * @returns {String|null}
- */
- const parseValue = function (str, startIndex, prefixToken, suffixTokens) {
- const idx = str.indexOf(prefixToken, startIndex);
- if (idx === -1) {
- return null;
- }
-
- let val = '';
- for (let i = idx + prefixToken.length; i < str.length; i++) {
- if (suffixTokens.indexOf(str[i]) !== -1) {
- break;
- }
-
- val += str[i];
- }
-
- return {
- "foundAtIndex": idx,
- "value": val
- }
- };
-
- /**
- *
- * @param {String} cssRuleStr
- * @returns {String[]}
- */
- const getUrlsFromCssString = function (cssRuleStr, selector = "url(", delimiters = [')'], mustEndWithQuote = false) {
- const urlsFound = [];
- let searchStartIndex = 0;
-
- while (true) {
- const url = parseValue(cssRuleStr, searchStartIndex, selector, delimiters);
- if (url === null) {
- break;
- }
- searchStartIndex = url.foundAtIndex + url.value.length;
- if (mustEndWithQuote && url.value[url.value.length - 1] !== '"') continue;
- const unquoted = removeQuotes(url.value);
- if (!unquoted /* || (!unquoted.startsWith('http')&& !unquoted.startsWith("/") )*/ || unquoted === 'http://' || unquoted === 'https://') {
- continue;
- }
-
- unquoted && urlsFound.push(unquoted);
- }
-
- return urlsFound;
- };
-
- /**
- *
- * @param {String} html
- * @returns {String[]}
- */
- const getImageUrlsFromFromHtml = function (html) {
- return getUrlsFromCssString(html, "src=", [' ', '>', '\t'], true);
- };
- const getSourceUrlsFromFromHtml = function (html) {
- return getUrlsFromCssString(html, "source=", [' ', '>', '\t'], true);
- };
-
- /**
- *
- * @param {String} str
- * @returns {String}
- */
- const removeQuotes = function (str) {
- return str.replace(/["']/g, "");
- };
-
- const escapeRegExp = function (string) {
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
- };
-
- /**
- *
- * @param {String} contentHtml
- * @param {Number} width
- * @param {Number} height
- *
- * @returns {Promise<String>}
- */
- const buildSvgDataUri = async function (webUrl, contentHtml, width, height, scroll) {
-
- return new Promise(async function (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 = "";
- let urlsFoundInCss = [];
-
- for (let i = 0; i < styleSheets.length; i++) {
- try {
- const rules = styleSheets[i].cssRules
- for (let j = 0; j < rules.length; j++) {
- const cssRuleStr = rules[j].cssText;
- urlsFoundInCss.push(...getUrlsFromCssString(cssRuleStr));
- cssStyles += cssRuleStr;
- }
- } catch (e) {
-
- }
- }
-
- // 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);
- // }
- // }
-
- contentHtml = contentHtml.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
- let urlsFoundInHtml = getImageUrlsFromFromHtml(contentHtml);
- const fetchedResources = await getMultipleResourcesAsBase64(webUrl, urlsFoundInHtml);
- for (let i = 0; i < fetchedResources.length; i++) {
- const r = fetchedResources[i];
- if (r.resourceUrl) {
- contentHtml = contentHtml.replace(new RegExp(escapeRegExp(r.resourceUrl), "g"), r.resourceBase64);
- }
- }
-
- const styleElem = document.createElement("style");
- styleElem.innerHTML = cssStyles.replace("&gt;", ">").replace("&lt;", "<");
-
- const styleElemString = new XMLSerializer().serializeToString(styleElem).replace(/&gt;/g, ">").replace(/&lt;/g, "<");
-
- // create DOM element string that encapsulates styles + content
- const contentRootElem = document.createElement("body");
- contentRootElem.style.zIndex = "1111";
- // contentRootElem.style.transform = "scale(0.08)"
- contentRootElem.innerHTML = styleElemString + contentHtml;
- contentRootElem.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
- //document.body.appendChild(contentRootElem);
-
- const contentRootElemString = new XMLSerializer().serializeToString(contentRootElem);
-
- // build SVG string
- const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='${width}' height='${height}'>
- <foreignObject x='0' y='${-scroll}' width='${width}' height='${scroll + height}'>
- ${contentRootElemString}
- </foreignObject>
- </svg>`;
-
- // convert SVG to data-uri
- const dataUri = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svg)))}`;
-
- resolve(dataUri);
- });
- };
-
- /**
- * @param {String} html
- * @param {Number} width
- * @param {Number} height
- *
- * @return {Promise<Image>}
- */
- this.renderToImage = async function (webUrl, html, width, height, scroll) {
- return new Promise(async function (resolve, reject) {
- const img = new Image();
- console.log("BUILDING SVG for:" + webUrl);
- img.src = await buildSvgDataUri(webUrl, html, width, height, scroll);
-
- img.onload = function () {
- console.log("IMAGE SVG created:" + webUrl);
- resolve(img);
- };
- });
- };
-
- /**
- * @param {String} html
- * @param {Number} width
- * @param {Number} height
- *
- * @return {Promise<Image>}
- */
- this.renderToCanvas = async function (webUrl, html, width, height, scroll) {
- return new Promise(async function (resolve, reject) {
- const img = await self.renderToImage(webUrl, html, width, height, scroll);
-
- const canvas = document.createElement('canvas');
- canvas.width = img.width;
- canvas.height = img.height;
-
- const canvasCtx = canvas.getContext('2d');
- canvasCtx.drawImage(img, 0, 0, img.width, img.height);
-
- resolve(canvas);
- });
- };
-
- /**
- * @param {String} html
- * @param {Number} width
- * @param {Number} height
- *
- * @return {Promise<String>}
- */
- this.renderToBase64Png = async function (webUrl, html, width, height, scroll) {
- return new Promise(async function (resolve, reject) {
- const canvas = await self.renderToCanvas(webUrl, html, width, height, scroll);
- resolve(canvas.toDataURL('image/png'));
- });
- };
-
-};
-
-
-export function CreateImage(webUrl, styleSheets, html, width, height, scroll) {
- const val = (new ForeignHtmlRenderer(styleSheets)).renderToBase64Png(webUrl, html.replace(/\n/g, "").replace(/<script((?!\/script).)*<\/script>/g, ""), width, height, scroll);
- return val;
-}
-
-
-
-var ClipboardUtils = new function () {
- var permissions = {
- 'image/bmp': true,
- 'image/gif': true,
- 'image/png': true,
- 'image/jpeg': true,
- 'image/tiff': true
- };
-
- function getType(types) {
- for (var j = 0; j < types.length; ++j) {
- var type = types[j];
- if (permissions[type]) {
- return type;
- }
- }
- return null;
- }
- function getItem(items) {
- for (var i = 0; i < items.length; ++i) {
- var item = items[i];
- if (item) {
- var type = getType(item.types);
- if (type) {
- return item.getType(type);
- }
- }
- }
- return null;
- }
- function loadFile(file, callback) {
- if (window.FileReader) {
- var reader = new FileReader();
- reader.onload = function () {
- callback(reader.result, null);
- };
- reader.onerror = function () {
- callback(null, 'Incorrect file.');
- };
- reader.readAsDataURL(file);
- } else {
- callback(null, 'File api is not supported.');
- }
- }
- this.readImage = function (callback) {
- if (navigator.clipboard) {
- var promise = navigator.clipboard.read();
- promise
- .then(function (items) {
- var promise = getItem(items);
- if (promise == null) {
- callback(null, null);
- return;
- }
- promise
- .then(function (result) {
- loadFile(result, callback);
- })
- .catch(function (error) {
- callback(null, 'Reading clipboard error.');
- });
- })
- .catch(function (error) {
- callback(null, 'Reading clipboard error.');
- });
- } else {
- callback(null, 'Clipboard is not supported.');
- }
- };
-};
-
-
-export function pasteImageBitmap(callback) {
- return ClipboardUtils.readImage(callback);
-} \ No newline at end of file