From 325e9d4c21117d8ff5e039af346e6485f25c49b2 Mon Sep 17 00:00:00 2001 From: Richard McKinney Date: Sun, 11 Feb 2024 22:32:18 +0000 Subject: [PATCH 1/3] Update Method_2_Script.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To organize the listed optimizations into thematic groupings and stack-ranked based on their anticipated impact, we can categorize them under headings such as **Code Structure**, **Efficiency and Performance**, **Readability and Maintainability**, and **Documentation and Cleanliness**. Within each category, the optimizations are ordered from most to least impactful based on their potential to improve the codebase. ### Code Structure 1. **Decomposed Functions**: Separating `processAndGeneratePDF`, `addImageToPDF`, `processValidImages`, and `handleAutoScrollAndGeneratePDF` into specific tasks significantly enhances modularity and clarity. This decomposition allows each function to be independently developed, tested, and reused, which is fundamental in software engineering. 2. **Avoid global variables**: Encapsulating variables like `i`, `doc`, `pdfDocumentName`, and `validImgTagCounter` within their respective functions prevents potential bugs caused by unintended modifications, crucial for maintaining a clean scope and preventing side effects. ### Efficiency and Performance 1. **Efficient DOM Access**: Minimizing DOM access by caching elements and using efficient selectors and methods directly impacts the performance, especially in a browser environment where DOM manipulation is costly. 2. **Use Array.prototype.forEach instead of for loops**: Leveraging `Array.from` and `forEach` not only improves readability but also efficiency by eliminating manual counter management and leveraging modern JavaScript optimizations. ### Readability and Maintainability 1. **Use const and let appropriately**: Using `const` for unchangeable variables makes the code easier to understand and debug by clearly indicating which variables are meant to remain constant, thereby preventing accidental reassignments. 2. **Use meaningful variable names**: Descriptive names improve the code's self-documentation, making it easier for new developers to understand what each variable represents without needing to decipher the code's logic. 3. **Improved Loop and Conditional Logic**: Streamlining logic for better readability and maintainability, crucial for complex conditions and loops. 4. **Use a single doc.addImage call**: Refactoring to avoid duplicate code improves maintainability by having a single point of update for future changes. 5. **Using arrow functions for setTimeout callbacks**: Enhances readability and succinctness, making asynchronous code more straightforward. ### Documentation and Cleanliness 1. **Dynamic Loading of jsPDF**: Adding comments to explain dynamic loading increases understandability, especially for developers unfamiliar with asynchronous script loading. 2. **Added comments explaining key operations**: Comprehensive comments describing the purpose and functionality of code sections, variables, and complex operations serve as an invaluable guide for new developers, enhancing the codebase's overall readability and maintainability. ### Additional Notes - Direct PDF Saving: This is implicitly covered under efficiency but is more of a specific improvement to streamline the file handling process. - Using template literals and removing the else clause are specific examples of improvements in **Readability and Maintainability** but are subsumed under the broader optimizations already listed. This thematic grouping and stack-ranking help highlight the importance of clear code structure, efficiency, readability, and cleanliness in developing maintainable and performant web applications. ___ Explanation of the Commenting Approach • Overall Structure: The code is broken down into functions, each with a specific role, enhancing modularity and readability. • Purpose of Each Function: Comments describe what each function does, the logic behind its implementation, and how it contributes to the overall goal of generating a PDF document. • Variable Descriptions: Comments explain the purpose of key variables, especially those whose roles might not be immediately clear to someone unfamiliar with the code. • Process Flow: The sequence of operations is explained, particularly how the asynchronous loading of the jsPDF library triggers the subsequent steps of the PDF generation process. • Decision Making: The rationale behind certain decisions, such as the calculation of scroll distances and the selection of elements for scrolling, is made clear. This commented version aims to make the codebase more accessible and understandable to new developers, facilitating easier modifications, debugging, and enhancements. --- Method_2_Script.js | 213 ++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 107 deletions(-) diff --git a/Method_2_Script.js b/Method_2_Script.js index 4bd138c..63df2ed 100644 --- a/Method_2_Script.js +++ b/Method_2_Script.js @@ -1,120 +1,119 @@ -let jspdf = document.createElement("script"); -jspdf.onload = function () { - let pdfDocumentName = "Document"; - let doc; - - function generatePDF (){ - let imgTags = document.getElementsByTagName("img"); - let checkURLString = "blob:https://drive.google.com/"; - let validImgTagCounter = 0; - for (i = 0; i < imgTags.length; i++) { - - if (imgTags[i].src.substring(0, checkURLString.length) === checkURLString){ - validImgTagCounter = validImgTagCounter + 1; - //console.log(imgTags[i].src); - let img = imgTags[i]; - - let canvas = document.createElement('canvas'); - let context = canvas.getContext("2d"); - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - //console.log("Width: " + img.naturalWidth + ", Height: " + img.naturalHeight); - context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight); - let imgDataURL = canvas.toDataURL(); - // console.log(imgDataURL); - - //let ratio; - let orientation; - if (img.naturalWidth > img.naturalHeight){ - //console.log("Landscape"); - orientation = "l"; - //ratio = img.naturalWidth/img.naturalHeight - }else { - //console.log("Portrait"); - orientation = "p"; - //ratio = img.naturalWidth/img.naturalHeight - } - - let scalefactor = 1.335; - let pageWidth = img.naturalWidth * scalefactor; - let pageHeight = img.naturalHeight * scalefactor; - //let imagexLeft = (pageWidth - img.naturalWidth)/2; - //let imagexTop = (pageHeight - img.naturalHeight)/2; - if (validImgTagCounter === 1){ - doc = new jsPDF({ - orientation: orientation, - unit: "px", - format: [pageWidth, pageHeight], - }); - doc.addImage(imgDataURL, "PNG", 0, 0, img.naturalWidth, img.naturalHeight); - }else{ - doc.addPage([pageWidth, pageHeight] , orientation); - doc.addImage(imgDataURL, "PNG", 0, 0, img.naturalWidth, img.naturalHeight); - } - } +// Function to dynamically load the jsPDF library and execute a callback function once it's loaded +function loadJsPDF(callback) { + // Create a new script element + let script = document.createElement("script"); + // Assign a callback function to be called once the script is fully loaded + script.onload = callback; + // Set the source URL of the script to the jsPDF library + script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js'; + // Append the script element to the body of the document, triggering the download and execution of the jsPDF script + document.body.appendChild(script); +} + +// Main function to process the page content and generate a PDF +function processAndGeneratePDF() { + // Initialize the document name with the desired output filename + const pdfDocumentName = "Document.pdf"; + // This variable will hold our jsPDF instance once it's created + let doc = null; + + // Function to add an individual image to the PDF document + function addImageToPDF(img) { + // Create a canvas element to draw the image on + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext("2d"); + // Set the canvas dimensions to match the image dimensions + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + // Draw the image onto the canvas + ctx.drawImage(img, 0, 0); + + // Convert the canvas content to a data URL that jsPDF can use + const imgData = canvas.toDataURL(); + // Determine the orientation of the image for the PDF layout + const orientation = img.naturalWidth > img.naturalHeight ? "l" : "p"; + // Set a scale factor to adjust the image size in the PDF + const scaleFactor = 1.335; + // Calculate the page dimensions based on the image size and scale factor + const pageWidth = img.naturalWidth * scaleFactor; + const pageHeight = img.naturalHeight * scaleFactor; + + // Check if the jsPDF instance exists, create it if not, or add a new page to it if it does + if (!doc) { + doc = new jsPDF({ + orientation, + unit: "px", + format: [pageWidth, pageHeight], + }); + } else { + doc.addPage([pageWidth, pageHeight], orientation); } - pdfDocumentName = pdfDocumentName + ".pdf"; - doc.save(pdfDocumentName); + // Add the image to the PDF document + doc.addImage(imgData, "PNG", 0, 0, img.naturalWidth, img.naturalHeight); } - let allElements = document.querySelectorAll("*"); - let chosenElement; - let heightOfScrollableElement = 0; - - for (i = 0; i < allElements.length; i++) { - if ( allElements[i].scrollHeight>=allElements[i].clientHeight){ - if (heightOfScrollableElement < allElements[i].scrollHeight){ - //console.log(allElements[i]); - //console.log(allElements[i].scrollHeight); - heightOfScrollableElement = allElements[i].scrollHeight; - chosenElement = allElements[i]; + // Function to identify valid images and process them for inclusion in the PDF + function processValidImages() { + // Retrieve all image elements from the document + const imgTags = document.getElementsByTagName("img"); + // Define the URL pattern to filter images that should be included in the PDF + const checkURLString = "blob:https://drive.google.com/"; + // Iterate over each image and add it to the PDF if it matches the pattern + Array.from(imgTags).forEach(img => { + if (img.src.startsWith(checkURLString)) { + addImageToPDF(img); } + }); + + // Once all valid images are processed, save the PDF document + if (doc) { + doc.save(pdfDocumentName); } } - if (chosenElement.scrollHeight > chosenElement.clientHeight){ - console.log("Auto Scroll"); - - let scrollDistance = Math.round(chosenElement.clientHeight/2); - //console.log("scrollHeight: " + chosenElement.scrollHeight); - //console.log("scrollDistance: " + scrollDistance); - - let loopCounter = 0; - function myLoop(remainingHeightToScroll, scrollToLocation) { - loopCounter = loopCounter+1; - console.log(loopCounter); - - setTimeout(function() { - if (remainingHeightToScroll === 0){ - scrollToLocation = scrollDistance; - chosenElement.scrollTo(0, scrollToLocation); - remainingHeightToScroll = chosenElement.scrollHeight - scrollDistance; - }else{ - scrollToLocation = scrollToLocation + scrollDistance ; - chosenElement.scrollTo(0, scrollToLocation); - remainingHeightToScroll = remainingHeightToScroll - scrollDistance; - } - - if (remainingHeightToScroll >= chosenElement.clientHeight){ - myLoop(remainingHeightToScroll, scrollToLocation) - }else{ - setTimeout(function() { - generatePDF(); - }, 1500) + // Function to handle scrolling for elements with significant scrollable content before generating the PDF + function handleAutoScrollAndGeneratePDF() { + // Identify all elements that have scrollable content + const elementsWithScroll = Array.from(document.querySelectorAll("*")).filter(el => el.scrollHeight > el.clientHeight); + // Select the element with the maximum scroll height to focus on + const chosenElement = elementsWithScroll.reduce((maxEl, currentEl) => currentEl.scrollHeight > (maxEl.scrollHeight || 0) ? currentEl : maxEl, {}); + + // Check if the chosen element requires scrolling + if (chosenElement.scrollHeight > chosenElement.clientHeight) { + console.log("Auto Scroll"); + // Initialize the remaining height to scroll through + let remainingHeight = chosenElement.scrollHeight; + // Calculate the distance to scroll each iteration, based on half the client height of the element + const scrollDistance = Math.round(chosenElement.clientHeight / 2); + + // Recursive function to scroll through the element and generate the PDF afterwards + function scrollAndGenerate() { + if (remainingHeight > 0) { + // Scroll the element by the calculated distance + chosenElement.scrollBy(0, scrollDistance); + // Subtract the scrolled distance from the remaining height + remainingHeight -= scrollDistance; + // Continue scrolling after a brief delay + setTimeout(scrollAndGenerate, 500); + } else { + // Once scrolling is complete, wait briefly before generating the PDF + setTimeout(processValidImages, 1500); } + } - }, 500) + // Start the scrolling process + scrollAndGenerate(); + } else { + // If no scrolling is needed, wait briefly before generating the PDF directly + console.log("No Scroll"); + setTimeout(processValidImages, 1500); } - myLoop(0, 0); - - }else{ - console.log("No Scroll"); - setTimeout(function() { - generatePDF(); - }, 1500) } -}; -jspdf.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js'; -document.body.appendChild(jspdf); + // Initiate the process of handling scrollable content and generating the PDF + handleAutoScrollAndGeneratePDF(); +} + +// Start the entire process by loading the jsPDF library and then executing the main function once it's loaded +loadJsPDF(processAndGeneratePDF); From 6a94db1453e5f3802e29fb5fa7ee308d7f1c3411 Mon Sep 17 00:00:00 2001 From: Richard McKinney Date: Sun, 11 Feb 2024 22:39:06 +0000 Subject: [PATCH 2/3] Update Method_1_Script.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code snippet is intended for generating a PDF data file by collecting image data URLs from a webpage and creating a downloadable text file containing these URLs. It also includes a mechanism to identify the tallest scrollable element on the page and auto-scroll through it before triggering the PDF data file generation. ___ Key Optimizations and Clarifications: • Use of const and let: Constants and block-scoped variables improve readability and prevent accidental reassignments. Array.from() for Iteration: Converts HTMLCollection to an array for easier manipulation. startsWith Method: More readable and direct than substring for checking URL prefixes. • Template Strings: Simplify concatenation, especially when adding line breaks between data URLs. • Isolated Function for Scrolling: Separates concerns by handling scrolling and PDF generation distinctly, enhancing code maintainability. • Recursive Scrolling Function: Clarified logic for progressively scrolling through the chosen element, with detailed comments explaining the process. This optimized version aims to improve upon the original by enhancing clarity, efficiency, and code organization, while also providing detailed comments to explain each step of the process. --- Method_1_Script.js | 194 +++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 95 deletions(-) diff --git a/Method_1_Script.js b/Method_1_Script.js index 4fb3474..9a4e1de 100644 --- a/Method_1_Script.js +++ b/Method_1_Script.js @@ -1,100 +1,104 @@ - - let pdfDocumentName = "Document"; - let doc = ""; - - function generatePDF_DataFile (){ - let imgTags = document.getElementsByTagName("img"); - let checkURLString = "blob:https://drive.google.com/"; - let validImgTagCounter = 0; - for (i = 0; i < imgTags.length; i++) { - - if (imgTags[i].src.substring(0, checkURLString.length) === checkURLString){ - validImgTagCounter = validImgTagCounter + 1; - //console.log(imgTags[i].src); - let img = imgTags[i]; - - let canvas = document.createElement('canvas'); - let context = canvas.getContext("2d"); - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - //console.log("Width: " + img.naturalWidth + ", Height: " + img.naturalHeight); - context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight); - let imgDataURL = canvas.toDataURL(); - // console.log(imgDataURL); - - if (doc === ""){ - doc = imgDataURL; - }else{ - doc = doc + "\n" + imgDataURL; - } - - } - } - - let anchorElement = document.createElement("a"); - let file = new Blob([doc], {type: 'text/plain'}); - - url = URL.createObjectURL(file); - anchorElement.href = url; - anchorElement.download = pdfDocumentName + ".PDF_DataFile"; - document.body.appendChild(anchorElement); - anchorElement.click(); +// Define the base name for the PDF document. +const pdfDocumentName = "Document"; + +// Initialize a variable to hold the concatenated data URLs of images. +let docDataUrls = ""; + +/** + * Extracts and encodes images from the current page into a downloadable file. + */ +function generatePDFDataFile() { + // Fetch all image elements on the page. + const imgTags = document.getElementsByTagName("img"); + // Define the prefix for URLs to be considered (specific to Google Drive hosted images). + const checkURLString = "blob:https://drive.google.com/"; + + // Iterate over all image tags to check and process valid images. + Array.from(imgTags).forEach(img => { + // Check if the image's source URL matches the defined prefix. + if (img.src.startsWith(checkURLString)) { + // Prepare a canvas to draw the image for data URL conversion. + const canvas = document.createElement('canvas'); + const context = canvas.getContext("2d"); + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight); + + // Convert the canvas content to a data URL. + const imgDataURL = canvas.toDataURL(); + // Append the new data URL to the document data, separated by newlines for multiple images. + docDataUrls += `${docDataUrls ? "\n" : ""}${imgDataURL}`; } - - let allElements = document.querySelectorAll("*"); - let chosenElement; - let heightOfScrollableElement = 0; - - for (i = 0; i < allElements.length; i++) { - if ( allElements[i].scrollHeight>=allElements[i].clientHeight){ - if (heightOfScrollableElement < allElements[i].scrollHeight){ - //console.log(allElements[i]); - //console.log(allElements[i].scrollHeight); - heightOfScrollableElement = allElements[i].scrollHeight; - chosenElement = allElements[i]; - } - } + }); + + // Create a Blob from the concatenated image data URLs. + const file = new Blob([docDataUrls], {type: 'text/plain'}); + // Generate a URL for the Blob. + const url = URL.createObjectURL(file); + // Create an anchor element for downloading the file. + const anchorElement = document.createElement("a"); + anchorElement.href = url; + anchorElement.download = `${pdfDocumentName}.PDF_DataFile`; + // Trigger the download. + document.body.appendChild(anchorElement); + anchorElement.click(); +} + +/** + * Identifies the tallest scrollable element and scrolls through it before generating the PDF data file. + */ +function autoScrollAndGeneratePDF() { + // Find all elements on the page. + const allElements = document.querySelectorAll("*"); + // Initialize variables to track the tallest scrollable element and its height. + let chosenElement = null; + let heightOfScrollableElement = 0; + + // Iterate over all elements to find the tallest scrollable one. + allElements.forEach(element => { + if (element.scrollHeight > element.clientHeight) { + if (heightOfScrollableElement < element.scrollHeight) { + chosenElement = element; + heightOfScrollableElement = element.scrollHeight; + } } - - if (chosenElement.scrollHeight > chosenElement.clientHeight){ - console.log("Auto Scroll"); - - let scrollDistance = Math.round(chosenElement.clientHeight/2); - //console.log("scrollHeight: " + chosenElement.scrollHeight); - //console.log("scrollDistance: " + scrollDistance); - - let loopCounter = 0; - function myLoop(remainingHeightToScroll, scrollToLocation) { - loopCounter = loopCounter+1; - console.log(loopCounter); - - setTimeout(function() { - if (remainingHeightToScroll === 0){ - scrollToLocation = scrollDistance; - chosenElement.scrollTo(0, scrollToLocation); - remainingHeightToScroll = chosenElement.scrollHeight - scrollDistance; - }else{ - scrollToLocation = scrollToLocation + scrollDistance ; - chosenElement.scrollTo(0, scrollToLocation); - remainingHeightToScroll = remainingHeightToScroll - scrollDistance; - } - - if (remainingHeightToScroll >= chosenElement.clientHeight){ - myLoop(remainingHeightToScroll, scrollToLocation) - }else{ - setTimeout(function() { - generatePDF_DataFile(); - }, 1500) - } - - }, 400) + }); + + // Check if a scrollable element was found and needs to be scrolled. + if (chosenElement && chosenElement.scrollHeight > chosenElement.clientHeight) { + console.log("Auto Scroll"); + const scrollDistance = Math.round(chosenElement.clientHeight / 2); + let remainingHeightToScroll = chosenElement.scrollHeight; + let scrollToLocation = 0; + + /** + * Recursively scrolls the chosen element until fully scrolled. + * @param {number} remainingHeight - Remaining height to scroll. + * @param {number} scrollTo - Current scroll target within the element. + */ + function myLoop(remainingHeight, scrollTo) { + setTimeout(() => { + scrollTo += scrollDistance; + chosenElement.scrollTo(0, scrollTo); + remainingHeight -= scrollDistance; + + if (remainingHeight > 0) { + myLoop(remainingHeight, scrollTo); + } else { + // After the final scroll, wait a moment before generating the PDF data file. + setTimeout(generatePDFDataFile, 1500); } - myLoop(0, 0); - - }else{ - console.log("No Scroll"); - setTimeout(function() { - generatePDF_DataFile(); - }, 1500) + }, 400); } + // Start the scrolling process. + myLoop(remainingHeightToScroll, scrollToLocation); + } else { + console.log("No Scroll Needed"); + // If no scrolling is needed, wait a moment before generating the PDF data file. + setTimeout(generatePDFDataFile, 1500); + } +} + +// Start the process. +autoScrollAndGeneratePDF(); From 47845d363e164951a5bc3c323e241bba23f18a35 Mon Sep 17 00:00:00 2001 From: Richard McKinney Date: Sun, 11 Feb 2024 23:08:33 +0000 Subject: [PATCH 3/3] Update README.md (Enhanced Documentation for Google Drive PDF Downloader) This PR updates the README documentation of the Google Drive PDF Downloader tool to enhance clarity, inclusivity, and user guidance. Key improvements include: - **Cross-Platform Compatibility**: Explicitly states the tool's compatibility with macOS, alongside Windows and Linux, ensuring users across all major operating systems know the tool is designed for their platform. - **Clarified Download and Save Instructions**: Provides detailed steps on how to save the **'.PDF_DataFile'** to the **'Input'** directory after downloading it from the browser. This update aims to eliminate confusion regarding where and how to properly place downloaded files for processing. - **Accessing the Web Console**: Offers straightforward instructions for opening the web console in Google Chrome and Brave browsers, including keyboard shortcuts for both Windows/Linux and macOS users. This guidance is intended to assist users unfamiliar with developer tools in easily executing the necessary scripts. - **Streamlined Steps and Tips**: Organizes information into clear, numbered steps and separates advanced tips for both download methods. This structure is designed to improve the readability and usability of the documentation, making it easier for users to follow the process and apply advanced options if needed. These enhancements aim to make the tool more accessible and user-friendly, supporting a wider range of users in efficiently downloading view-only PDFs from Google Drive. --- README.md | 136 +++++++++++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 9d599c2..d4e47f3 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,57 @@ -# Google Drive PDF Downloader - -This script will help you to download protected view only PDF files from Google Drive easily. - -## Features -* Lets you to download high quality PDF files. -* Saves all pages individually inside a directory called Pages. -* Fast download speed. -* Efficient CPU and RAM usage. -* Automatically adjusts the page size and orientation according to the source document. -* Automatic fast scrolling to load all the pages correctly. -* Supports Windows, Linux etc. - -## How to use - Method 1 -### This method is fast, works for all types of scenarios and performance is great! -1. Download this repository to your computer and unzip it. -2. Enter the URL of the protected view only PDF File into your browser. (eg: Firefox, Chrome etc.) -3. Open the script **"Method_1_Script.js"** and copy all the contents. -4. Then open the browser web console. -5. Paste the copied script into the console and press enter. -6. After few seconds the browser will prompt you to save a file with extension **".PDF_DataFile"** -7. Save this file and copy it into the **"Input"** directory which is inside the repository you downloaded earlier! -8. If you are using Windows then navigate to **"Windows"** directory and double click on **"GeneratePDF.cmd"**, or If you are using Linux then navigate to **"Linux"** directory and execute **"GeneratePDF"** -9. A successful message will be shown once the whole process completes. -10. Navigate to the **"Output"** directory and enjoy! - -## Tips for Method 1 -* You should always give a custom file name by changing the place holder "Document" to "Cool_File_Name" in **Method_1_Script.js**. Do not include **".pdf"** file extension along with the document name here! -``` -let pdfDocumentName = "Document"; -``` -Change to this -``` -let pdfDocumentName = "Cool_File_Name"; -``` -* By default this script will download PDF file with the highest quality available, but just in case if you need even better quality simply zoom in your browser (eg: 200% to 300%) then follow the above steps to download. -* The Output directory contains individual PDF directories for efficient organizing and **"Pages"** directory is present in each one of these. -* The **"Pages"** directory contains individual pages of PDF document in .png format. -* For bulk PDF generation, download all **".PDF_DataFile"** for your viewonly PDF documents and copy these inside **"Input"** directory then double click on **"GeneratePDF.cmd"** to execute (For Linux execute **"GeneratePDF"** which is inside the **"Linux"** directory). -* During execution of **"GeneratePDF.cmd"**, PDF directory will be creates inside **"Output"** directory based on the custom **"pdfDocumentName"** given earlier. -If the PDF directory name already present in **"Output"** directory, then it will ask user's permission to delete it. Just Press **"Y"** for YES or **"N"** for NO. If you press N then it will skip processing of that specific **".PDF_DataFile"** and it's PDF won't be generated. - -## How to use - Method 2 -#### Use this method only for PDF with less than 20 pages, if you experience any errors or slow down then follow Method 1 -1. Enter the URL of the protected view only PDF File into your browser. (eg: Firefox, Chrome etc.) -2. Open the script **"Method_2_Script.js"** and copy all the contents. -3. Then open the browser web console. -4. Paste the copied script into the console and press enter. -5. After few seconds the browser will prompt you to save the PDF file. -6. Save the file and enjoy! - -## Tips for Method 2 -* You should give a custom file name by changing the place holder "Document" to "Cool_File_Name" in **"Method_2_Script.js"**. Do not include **".pdf"** file extension along with the document name here! -``` -let pdfDocumentName = "Document"; -``` -Change to this -``` -let pdfDocumentName = "Cool_File_Name"; -``` -* By default this script will download PDF file with the highest quality available, but just in case if you need even better quality simply zoom in your browser (eg: 130% to 150%) then follow the above steps to download. If you increase the zoom level more than 150% Method_2_Script.js will struggle to generate the PDF. - -## Author -* **Pala** - [Follow me on Instagram!](https://www.instagram.com/pala_zeltox/) -Feel free to contact me for projects. - -## Inspiration -Inspired from https://codingcat.codes/2019/01/09/download-view-protected-pdf-google-drive-js-code/ - -## Dependencies -* Used [ImageMagick](https://github.com/ImageMagick/ImageMagick/) to generate PDF for Method 1 -* Used [jsPDF](https://github.com/MrRio/jsPDF) to generate PDF for Method 2 - - -## Security Tips! -* Always be aware of what you paste into the browser console, malicious code can do alot of harm. - - - +# Advanced Google Drive PDF Downloader Manual + +Efficiently download high-quality, view-only PDFs from Google Drive using this script. It's designed for optimal performance, minimal resource usage, and is compatible with macOS, Windows, and Linux. + +## Feature Highlights +- High-quality PDF downloads. +- Organizes PDF pages into a "Pages" directory. +- Fast download speeds with low CPU and RAM usage. +- Auto-adjusts PDF page size and orientation to match the source. +- Ensures complete page loading through automatic fast scrolling. +- Cross-platform support (Windows, Linux, macOS). + +## Getting Started + +### Method 1: Universal Solution +This method is robust, ensuring excellent performance across different scenarios, including macOS. + +#### Steps to Use: +1. **Repository Setup**: Download and unzip this repository on your computer. +2. **Open PDF**: Go to the Google Drive view-only PDF file in your browser. +3. **Script Copy**: Open **"Method_1_Script.js"** from the repository, copy its contents. +4. **Execute in Web Console**: + - For Chrome/Brave: Press `Ctrl+Shift+J` (Windows/Linux) or `Cmd+Option+J` (macOS) to open the console. + - Paste the script and press Enter. +5. **File Saving**: A prompt will ask you to save a **".PDF_DataFile"**. Save it to the **"Input"** folder, located within the repository you've just unzipped. +6. **Generate PDF**: + - On Windows, go to the **"Windows"** folder and run **"GeneratePDF.cmd"**. + - On macOS/Linux, navigate to the **"Linux"** folder, and execute **"GeneratePDF"** via terminal. +7. **Retrieve PDF**: After processing, your PDF will be in the **"Output"** folder. + +#### Enhanced Tips for Method 1: +- **Custom Naming**: Change the placeholder in **"Method_1_Script.js"** to a desired filename. Ensure ".pdf" extension is not added. +- **Quality Boost**: For improved resolution, increase browser zoom (200%-300%) prior to script execution. +- **Batch Downloads**: Place all **".PDF_DataFile"**s in the **"Input"** folder for bulk processing. + +### Method 2: For Shorter Documents +Optimal for documents under 20 pages. Switch to Method 1 for larger documents or if performance issues occur. + +#### Quick Start: +1. **Access PDF**: Visit the Google Drive PDF's URL in a browser. +2. **Script Preparation**: Copy all content from **"Method_2_Script.js"**. +3. **Web Console Execution**: + - Open the console (use `Ctrl+Shift+J` or `Cmd+Option+J`). + - Paste the script and hit Enter. +4. **PDF Download**: Save the PDF file when prompted. + +#### Method 2 Tips: +- **Custom Filenames**: Adjust the filename in **"Method_2_Script.js"** by editing the placeholder. +- **Zoom for Quality**: Set zoom to 130%-150% for better quality, noting limits at higher zoom levels. + +## Author & Acknowledgments +- **Pala**: Innovative scripting solutions. [Instagram](https://www.instagram.com/pala_zeltox/). +- Inspired by https://codingcat.codes. +- Uses [ImageMagick](https://github.com/ImageMagick/ImageMagick/) and [jsPDF](https://github.com/MrRio/jsPDF). + +## Security Notice +Be cautious with scripts in your browser console. Always verify the script's source to prevent security risks.