const JSZip = require('jszip'); window.ExportHtml = (Popup) => { const saveAs = function(blob, filename) { let dl = document.createElement('a'); dl.href = window.URL.createObjectURL(blob); dl.onclick = event => document.body.removeChild(event.target); dl.style.display = 'none'; dl.target = '_blank'; dl.download = filename; document.body.appendChild(dl); dl.click(); }; const asyncForEach = async function (array, callback) { for (let index = 0; index < array.length; index++) { await callback(array[index], index, array); } }; const getPageHtmlString = () => { return `${ window.document.querySelector('html').outerHTML }`; }; const removeAnchors = htmlString => { const replaceOpenAnchor = htmlString.replace(new RegExp(' { document.querySelector('.board-sidebar.sidebar').remove(); }; const addJsonExportToZip = async (zip, boardSlug) => { const downloadJSONLink = document.querySelector('.download-json-link'); const downloadJSONURL = downloadJSONLink.href; const response = await fetch(downloadJSONURL); const responseBody = await response.text(); zip.file(`data/${boardSlug}.json`, responseBody); }; const closeSidebar = () => { document.querySelector('.board-header-btn.js-toggle-sidebar').click(); }; const cleanBoardHtml = () => { Array.from(document.querySelectorAll('script')).forEach(elem => elem.remove(), ); Array.from( document.querySelectorAll('link:not([rel="stylesheet"])'), ).forEach(elem => elem.remove()); document.querySelector('#header-quick-access').remove(); Array.from( document.querySelectorAll('#header-main-bar .board-header-btns'), ).forEach(elem => elem.remove()); Array.from(document.querySelectorAll('.list-composer')).forEach(elem => elem.remove(), ); Array.from( document.querySelectorAll( '.list-composer,.js-card-composer, .js-add-card', ), ).forEach(elem => elem.remove()); Array.from( document.querySelectorAll('.js-perfect-scrollbar > div:nth-of-type(n+2)'), ).forEach(elem => elem.remove()); Array.from(document.querySelectorAll('.js-perfect-scrollbar')).forEach( elem => { elem.style = 'overflow-y: auto !important;'; elem.classList.remove('js-perfect-scrollbar'); }, ); Array.from(document.querySelectorAll('[href]:not(link)')).forEach(elem => elem.attributes.removeNamedItem('href'), ); Array.from(document.querySelectorAll('[href]')).forEach(elem => { // eslint-disable-next-line no-self-assign elem.href = elem.href; // eslint-disable-next-line no-self-assign elem.src = elem.src; }); Array.from(document.querySelectorAll('.is-editable')).forEach(elem => { elem.classList.remove('is-editable') }) }; const getBoardSlug = () => { return window.location.href.split('/').pop(); }; const getStylesheetList = () => { return Array.from( document.querySelectorAll('link[href][rel="stylesheet"]'), ); }; const downloadStylesheets = async (stylesheets, zip) => { await asyncForEach(stylesheets, async elem => { const response = await fetch(elem.href); const responseBody = await response.text(); const finalResponse = responseBody.replace( new RegExp('packages\/[^\/]+\/upstream\/', 'gim'), '../' ); const filename = elem.href .split('/') .pop() .split('?') .shift(); const fileFullPath = `style/${filename}`; zip.file(fileFullPath, finalResponse); elem.href = `../${fileFullPath}`; }); }; const getSrcAttached = () => { return Array.from(document.querySelectorAll('[src]')); }; const downloadSrcAttached = async (elements, zip, boardSlug) => { await asyncForEach(elements, async elem => { const response = await fetch(elem.src); const responseBody = await response.blob(); const filename = elem.src .split('/') .pop() .split('?') .shift(); const fileFullPath = `${boardSlug}/${elem.tagName.toLowerCase()}/${filename}`; zip.file(fileFullPath, responseBody); elem.src = `./${elem.tagName.toLowerCase()}/${filename}`; }); }; const removeCssUrlSurround = url => { const working = url || ""; return working .split("url(") .join("") .split("\")") .join("") .split("\"") .join("") .split("')") .join("") .split("'") .join("") .split(")") .join(""); }; const getCardCovers = () => { return Array.from(document.querySelectorAll('.minicard-cover')) .filter(elem => elem.style['background-image']) } const downloadCardCovers = async (elements, zip, boardSlug) => { await asyncForEach(elements, async elem => { const response = await fetch(removeCssUrlSurround(elem.style['background-image'])); const responseBody = await response.blob(); const filename = removeCssUrlSurround(elem.style['background-image']) .split('/') .pop() .split('?') .shift() .split('#') .shift(); const fileFullPath = `${boardSlug}/covers/${filename}`; zip.file(fileFullPath, responseBody); elem.style = "background-image: url('" + `covers/${filename}` + "')"; }); }; const addBoardHTMLToZip = (boardSlug, zip) => { ensureSidebarRemoved(); const htmlOutputPath = `${boardSlug}/index.html`; zip.file(htmlOutputPath, new Blob([ removeAnchors(getPageHtmlString()) ], { type: 'application/html' })); }; return async () => { const zip = new JSZip(); const boardSlug = getBoardSlug(); await addJsonExportToZip(zip, boardSlug); Popup.close(); closeSidebar(); cleanBoardHtml(); await downloadStylesheets(getStylesheetList(), zip); await downloadSrcAttached(getSrcAttached(), zip, boardSlug); await downloadCardCovers(getCardCovers(), zip, boardSlug); addBoardHTMLToZip(boardSlug, zip); const content = await zip.generateAsync({ type: 'blob' }); saveAs(content, `${boardSlug}.zip`); window.location.reload(); } };