Skip to content

Instantly share code, notes, and snippets.

@wefluidmedia-prog
Last active December 9, 2025 12:47
Show Gist options
  • Select an option

  • Save wefluidmedia-prog/c517564f7225953e68b139ef70a7ad2e to your computer and use it in GitHub Desktop.

Select an option

Save wefluidmedia-prog/c517564f7225953e68b139ef70a7ad2e to your computer and use it in GitHub Desktop.
"A DOM reconstruction tool for Canvas-based PDF viewers."
// Secure, Bulletproof PDF Downloader (Sorts & Compresses)
(async function() {
'use strict';
// --- CONFIG ---
const JSLIB_URL = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js';
const IMG_QUALITY = 0.8; // 0.8 is the sweet spot for 500+ pages. 1.0 will crash Chrome.
const PROCESS_DELAY = 20; // ms to wait between pages to keep UI responsive
// --------------
// 1. Trusted Types Policy (Bypass Content-Security-Policy)
let trustedURL = JSLIB_URL;
if (window.trustedTypes && window.trustedTypes.createPolicy) {
if (!window.trustedTypes.defaultPolicy) {
const policyName = 'jsPdfLoader_' + Math.floor(Math.random() * 10000);
const policy = window.trustedTypes.createPolicy(policyName, {
createScriptURL: (input) => {
if (input === JSLIB_URL) return input;
throw new Error('Security Violation: Unauthorized Script URL.');
}
});
trustedURL = policy.createScriptURL(JSLIB_URL);
}
}
// 2. Library Loader
const loadScript = (src) => {
return new Promise((resolve, reject) => {
if (window.jspdf) { resolve(); return; }
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.body.appendChild(script);
});
};
try {
console.log("[*] Injecting jsPDF...");
await loadScript(trustedURL);
// 3. Intelligent Element Selection & Sorting
console.log("[*] Scanning DOM for images...");
// Convert HTMLCollection to Array
let rawElements = Array.from(document.getElementsByTagName("img"));
// Filter: Must be a Blob (loaded) and have dimensions
let validElements = rawElements.filter(img =>
img.src.startsWith('blob:') &&
img.naturalWidth > 100 && // Filter out tiny icons
img.naturalHeight > 100
);
if (validElements.length === 0) {
throw new Error("No images found. Did you scroll the document to load them?");
}
console.log(`[*] Found ${validElements.length} candidate images. Sorting by vertical position...`);
// Sort by Y position (Top to Bottom) to fix any DOM ordering issues
validElements.sort((a, b) => {
const rectA = a.getBoundingClientRect();
const rectB = b.getBoundingClientRect();
// Compare Y position. If Y is same, compare X (unlikely for vertical PDF but safe)
return (rectA.top + window.scrollY) - (rectB.top + window.scrollY);
});
// Initialize PDF
const pdf = new jsPDF();
let pagesProcessed = 0;
console.log(`[*] Starting processing of ${validElements.length} pages...`);
// 4. Processing Loop
for (let i = 0; i < validElements.length; i++) {
const img = validElements[i];
try {
// Create disposable canvas
let canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Compress to JPEG
const imgData = canvas.toDataURL("image/jpeg", IMG_QUALITY);
// Cleanup canvas immediately to free memory
canvas.width = 1;
canvas.height = 1;
canvas = null;
// PDF Logic
const imgProps = pdf.getImageProperties(imgData);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'JPEG', 0, 0, pdfWidth, pdfHeight);
pagesProcessed++;
// Only add a new page if we aren't at the last one
if (i < validElements.length - 1) {
pdf.addPage();
}
// Logging progress every 10 pages or so
if (i % 10 === 0) {
console.log(`[+] Processed Page ${i + 1}/${validElements.length}`);
}
// Prevent UI Freeze
await new Promise(r => setTimeout(r, PROCESS_DELAY));
} catch (err) {
console.error(`[!] Error processing page ${i + 1}:`, err);
// Continue loop even if one page fails
}
}
console.log(`[*] Success. Saving ${pagesProcessed} pages to PDF...`);
pdf.save("Complete_Document.pdf");
} catch (e) {
console.error("[-] Critical Failure:", e);
alert("Script failed. Check console for details.");
}
})();
@wefluidmedia-prog
Copy link
Author

Step by step guide to downloading protected PDF from Google Drive
Open the document in Google Docs
Scroll to the bottom of the document, so all the pages are present
Open Developer Tools on separate window and choose the Console tab
Paste the code
Have fun!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment