diff --git a/web-extension/extractHtml.js b/web-extension/extractHtml.js index ef56046..27c4497 100644 --- a/web-extension/extractHtml.js +++ b/web-extension/extractHtml.js @@ -18,7 +18,7 @@ var allowedTags = [ 'math', 'maction', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'msgroup', 'mlongdiv', 'mscarries', 'mscarry', 'mstack', 'semantics' - // TODO ? + // TODO ? // ,'form', 'button' // TODO svg support ? @@ -38,12 +38,12 @@ var tmpIdsToNewCssSTRING = {}; var supportedCss = [ 'background-color', 'border', - 'color', + 'color', 'font', 'line-height', 'list-style', 'padding', - 'text-align', + 'text-align', ]; ////// @@ -73,7 +73,7 @@ function getImageSrc(srcTxt) { filename: newImgFileName, // TODO name data: getBase64ImgData(srcTxt) }); - } else { + } else { allImages.push({ originalUrl: getImgDownloadUrl(srcTxt), filename: newImgFileName, // TODO name @@ -117,29 +117,53 @@ function extractSvgToImg($htmlObject) { } // replaces all iframes by divs with the same innerHTML content -function extractIFrames() { - let allIframes = document.getElementsByTagName('iframe') - let changeIFrames = [] - let newDivs = [] - for (let iFrame of allIframes) { - if (!iFrame.contentDocument || !iFrame.contentDocument.body) { - continue +function extractIFrames(iframes, prefix = "") { + if (!iframes.length) { + return; + } + + function addIdInStyle(style, id) { + return style.split("{").map(function (segment) { + const selectors = segment.split("}"); + // if the CSS is well formed, selectors may be 1 element (for the first + // rule) or 2 elements array. Last element is the one which contains the + // actual selectors. + selectors[selectors.length - 1] = selectors[selectors.length - 1] + .split(",") + .map(function (selector) { + return ( + selector.trim().length > 0//check if it's just an empty line + ? "#" + id + " " + selector.replace("body", "") + : selector + ); + }); + return selectors.join("}"); + }).join("{"); + } + + const divs = iframes.map(function (iframe, index) { + const div = document.createElement("div"); + div.id = prefix + "save-as-ebook-iframe-" + index; + if (!iframe.contentDocument || !iframe.contentDocument.body) { + console.log("CORS not enabled or empty iframe. Discarding " + div.id); + return div; } - let bodyContent = iFrame.contentDocument.body.innerHTML - let bbox = iFrame.getBoundingClientRect() - let newDiv = document.createElement('div') - newDiv.style.width = bbox.width - newDiv.style.height = bbox.height - newDiv.innerHTML = bodyContent - changeIFrames.push(iFrame) - newDivs.push(newDiv) - } - for (let i = 0; i < newDivs.length; i++) { - let newDiv = newDivs[i] - let iFrame = changeIFrames[i] - let iframeParent = iFrame.parentNode - iframeParent.replaceChild(newDiv, iFrame) - } + const bbox = iframe.getBoundingClientRect(); + div.style.width = bbox.width; + div.style.height = bbox.height; + console.log(div.id); + div.innerHTML = iframe.contentDocument.body.innerHTML; + Array.from(div.querySelectorAll("style")).forEach(function (style) { + style.innerHTML = addIdInStyle(style.innerHTML, div.id); + }); + + return div; + }); + iframes.forEach((iframe, i) => iframe.parentNode.replaceChild(divs[i], iframe)); + return divs.forEach((div, i) => extractIFrames( + Array.from(div.querySelectorAll("iframe")), + i + "-" + )); } function preProcess($htmlObject) { @@ -381,7 +405,7 @@ function extractCss(includeStyle, appliedStyles) { function deferredAddZip(url, filename) { let deferred = $.Deferred(); - JSZipUtils.getBinaryContent(url, function(err, data) { + JSZipUtils.getBinaryContent(url, function(err, data) { if (err) { // deferred.reject(err); TODO console.log('Error:', err); @@ -408,13 +432,13 @@ function deferredAddZip(url, filename) { } tmpGlobalContent = tmpGlobalContent.replace(oldFilename, filename) } - + extractedImages.push({ filename: filename, // TODO - must be JSON serializable data: base64ArrayBuffer(data) }); - + deferred.resolve(); } }); @@ -428,7 +452,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { let tmpContent = ''; let styleFile = null; - extractIFrames() + extractIFrames(Array.from(document.querySelectorAll("iframe"))); if (request.type === 'extract-page') { styleFile = extractCss(request.includeStyle, request.appliedStyles)