const JSZip = require('jszip'); window.ExportHtml = Popup => { const saveAs = function(blob, filename) { const 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('[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(); }; };