-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBookmark Javascript
1 lines (1 loc) · 5.36 KB
/
Bookmark Javascript
1
javascript: (async () => { let s = prompt("List scopes separated by spaces (e.g., *.example.com github.com) or leave blank for all domains", ""); let scopes = s ? s.split(" ").map(scope => scope.replace(/\*/g, ".*")) : [".*"]; let tags = document.getElementsByTagName("script"); const rel = /["'](\/[\w./\-_?=&]*)["']/g; const abs = /(["'])(https?:\/\/(?:www\.)?[^\s'"]+?)\1/g; const file = /\.(pdf|docx?|xlsx?|pptx?|js|css|jpg|jpeg|png|gif|bmp|svg|mp3|mp4|avi|mov|txt|csv|json|xml|zip|rar|7z|exe|woff2?|otf)$/i; async function fetchFile(url) { try { return (await fetch(url, { mode: 'cors' })).text(); } catch (e) { console.error("Fetch error for:", url, e); return ""; } } function createTable(entries) { let locations = [...new Set(entries.map(entry => entry.file))]; let t = `<style>body { font-family: Arial, sans-serif; margin: 20px; } table { border-collapse: collapse; width: 100%; } th, td { padding: 10px; text-align: left; border: 1px solid #ddd; } th { background-color: #f4f4f4; } tr:nth-child(even) { background-color: #f9f9f9; } select { margin: 10px; padding: 8px; font-size: 16px; } a { display: inline-block; margin-left: 10px; } a img { width: 24px; vertical-align: middle; } button { margin: 10px; padding: 8px 16px; font-size: 16px; cursor: pointer; } div { display: flex; align-items: center; flex-wrap: wrap; } div > * { margin: 0 5px; } div > .creators { margin-left: auto; }</style><div><select id="locationFilter" style="margin-right:10px;margin-bottom:10px;"><option value="">All Locations</option>${locations.map(loc => `<option value="${loc}">${loc}</option>`).join('')}</select><button id="copyUrls" style="margin-bottom:10px;">Copy URLs</button><button id="saveHtml" style="margin-bottom:10px;">Save as HTML</button><div class="creators" style="margin-bottom:10px;"><span>Creators:</span><a href="https://github.com/Hacking-Notes" target="_blank"><img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub Logo"></a><a href="https://github.com/AtlasWiki" target="_blank"><img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub Logo"></a></div></div><table><thead><tr><th>Location</th><th>Endpoint</th><th>Extension</th><th>Link</th></tr></thead><tbody>${entries.filter(entry => entry.url !== "/").map((entry, index) => { let ext = [...new Set((entry.url.match(file) || []).map(e => e.trim()))].join(","); let id = `endpoint-${index}`; return `<tr><td>${entry.file}</td><td>${entry.url}</td><td>${ext}</td><td><a href="${entry.file}#${id}" target="_blank" onclick="window.open('${entry.file}','_blank').addEventListener('load',()=>document.getElementById('${id}')?.scrollIntoView())">Open File</a></td></tr>`; }).join('')}</tbody></table>`; return t; } function filterTable() { let filter = document.getElementById('locationFilter').value; document.querySelectorAll('table tbody tr').forEach(row => { row.style.display = (filter === "" || row.querySelector('td:first-child').textContent === filter) ? '' : 'none'; }); } function parseFiles() { return Promise.all(Array.from(tags).map(tag => { let src = tag.src; return scopes.some(scope => new RegExp(`https?://${scope}`).test(src)) ? fetchFile(src).then(c => { let rUrls = Array.from(c.matchAll(rel), m => ({ url: m[1], file: src })); let aUrls = Array.from(c.matchAll(abs), m => ({ url: m[2], file: src })); let allUrls = new Set([...rUrls, ...aUrls]); return Array.from(allUrls); }).catch(e => { console.error("Error:", e); return []; }) : Promise.resolve([]); })); } function parsePage() { let c = document.documentElement.outerHTML; let rUrls = Array.from(c.matchAll(rel), m => ({ url: m[1], file: document.location.href })); let aUrls = Array.from(c.matchAll(abs), m => ({ url: m[2], file: document.location.href })); let allUrls = new Set([...rUrls, ...aUrls]); return parseFiles().then(fileUrls => { let combinedUrls = new Map([...allUrls, ...fileUrls.flat()].map(u => [u.url, u])); let uniqueUrls = [...combinedUrls.values()]; let html = `<html><head><title>URL Results</title></head><body>${createTable(uniqueUrls)}<script>function filterTable() { let filter = document.getElementById('locationFilter').value; document.querySelectorAll('table tbody tr').forEach(row => { row.style.display = (filter === "" || row.querySelector('td:first-child').textContent === filter) ? '' : 'none'; }); } document.getElementById('locationFilter').addEventListener('change', filterTable); document.getElementById('copyUrls').addEventListener('click', () => { let rows = document.querySelectorAll('table tbody tr'); let urls = []; rows.forEach(row => { let domain = row.querySelector('td:first-child').textContent.split('/').slice(0, 3).join('/'); let url = row.querySelector('td:nth-child(2)').textContent; if (!url.startsWith('http') && !url.startsWith('//')) { urls.push(domain + url); } }); navigator.clipboard.writeText(urls.join('\\n')).then(() => { alert('URLs copied to clipboard!'); }).catch(e => console.error('Copy error:', e)); }); document.getElementById('saveHtml').addEventListener('click', () => { let blob = new Blob([document.documentElement.outerHTML], { type: 'text/html' }); let url = URL.createObjectURL(blob); let a = document.createElement('a'); a.href = url; a.download = 'page.html'; a.click(); URL.revokeObjectURL(url); });</script></body></html>`; let newTab = window.open(); newTab.document.write(html); newTab.document.close(); }).catch(e => console.error("Parse Page Error:", e)); } parsePage(); })();