/** HTML escape */ function escapeHtml(unsafe) { return unsafe .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } /** Escape URL chars that could throw off the meta redirect tag */ function sanitizeUrl(unsafe) { return unsafe .replace(/;/g, "%3B"); } /** * Remove the most risky characters from a filename string * * Firefox doesn't allow these: |"*?:<> */ function cleanFilename(unsafe) { return unsafe .replace(/::/g, " - ") // common delimiter (e.g. My Cool Article :: Website.com) .replace(/[?*]+/g, " ") // this is just noise, drop it .replace(/[\<\[]/g, "(") .replace(/[\>\]]/g, ")") .replace(/ :/g, " -") .replace(/: /g, " ") .replace(/:/g, "_") .replace(/"/g, "'") // firefox hates double quote .replace(/[/\\|]/g, "-") // porobable delimiters that should be kept in some form .replace(/-+/g, "-") // collapse multiple hyphen (may result from substitutions) .replace(/[\+=]/g, "_") // other suspicious stuff .replace(/\s+/g, " ") // collapse multiple whitespace .replace(/[\._,-]+$/g, "") // the filename should not end on special chars .replace(/^[\._,-]+/g, "") // nor start .trim(); } browser.browserAction.onClicked.addListener((tab) => { const escapedUrl = escapeHtml(sanitizeUrl(tab.url)); const escapedTitle = escapeHtml(tab.title); const filename = cleanFilename(tab.title); console.log(`Escaped URL: "${escapedUrl}"`); console.log(`Escaped title: "${escapedTitle}"`); console.log(`Saving as: "${filename}"`); const html = ` ${escapedTitle} Redirecting to: ${escapedUrl} `; const content = new Blob([html]); //console.log(`Generated HTML:\n${html}`); browser.downloads.download({ filename: `${filename}.link.html`, url: URL.createObjectURL(content) }); });