Skip to content

Instantly share code, notes, and snippets.

@billgateswhynot
Last active February 22, 2026 22:53
Show Gist options
  • Select an option

  • Save billgateswhynot/370e074ed23d8a9a917d09d013b9cdd2 to your computer and use it in GitHub Desktop.

Select an option

Save billgateswhynot/370e074ed23d8a9a917d09d013b9cdd2 to your computer and use it in GitHub Desktop.
Download view only protected presentation from Google Drive

Step by step guide to downloading protected presentation from Google Drive.

  1. Open the document in Google Docs.
  2. Update the access url, replace the display mode at the end of the url from /edit to /htmlpresent:
  3. Scroll down to the bottom of the document to make sure all pages have loaded.
  4. Open Developer Tools - Console:
    • If you are previewing in Google Chrome or Firefox: Press Shift + Ctrl + J ( on Windows / Linux) or Option + ⌘ + J (on Mac).
    • If you are previewing in Microsoft Edge Press Shift + Ctrl + I.
    • If you are previewing in Apple Safari Press Option + ⌘ + C.
  5. Paste below code and press Enter. The pdf file will now start downloading. This may take a few minutes depending on the number of pages in the document.
let trustedURL_jspdf;
let trustedURL_domtoimage;

if (window.trustedTypes && trustedTypes.createPolicy) {
    const policy = trustedTypes.createPolicy('myPolicy', {
        createScriptURL: (input) => input
    });

    trustedURL_jspdf = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js');
    trustedURL_domtoimage = policy.createScriptURL('https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js');
} else {
    trustedURL_jspdf = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js';
    trustedURL_domtoimage = 'https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js';
}

const script1 = document.createElement('script');
script1.src = trustedURL_jspdf;
document.head.appendChild(script1);

const script2 = document.createElement('script');
script2.src = trustedURL_domtoimage;
document.head.appendChild(script2);

script1.onload = script2.onload = function() {
    if (window.jspdf && window.domtoimage) {
        console.log('Both libraries loaded successfully');
        createPDFWithImages();
    } else {
        console.error('Failed to load the libraries');
    }
};

async function translateText(text, sourceLang = 'auto', targetLang = 'fr') { //translate to french
    const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;

    try {
        const response = await fetch(url);
        const data = await response.json();

        const translatedText = data[0].map(item => item[0]).join(' ');

        return translatedText;
    } catch (error) {
        console.error('Translate error:', error);
        return null;
    }
}

function getSlideNotesText(slideNotes) {
    if (!slideNotes) {
        console.log('Not found: class "slide-notes"');
        return '';
    }

    const paragraphs = slideNotes.querySelectorAll('p');
    const textContent = Array.from(paragraphs)
        .map(p => p.textContent.trim())
        .join(' \n ');

    return textContent;
}

const createPDFWithImages = async () => {
    const {
        jsPDF
    } = window.jspdf;

    const doc = new jsPDF({
        orientation: 'l',
        unit: 'mm',
        format: 'a4',
        compressPDF: true
    });
    const slides = document.querySelectorAll('div.slide');

    const pageWidth = doc.internal.pageSize.getWidth();
    const pageHeight = doc.internal.pageSize.getHeight();
    const margin = 0;

    for (let i = 0; i < slides.length; i++) {
        const slide = slides[i];

        const content = slide.querySelector('.slide-content');
        const notes = slide.querySelector('.slide-notes');
        content.style.margin = '0';

        await window.domtoimage.toPng(content)
            .then((imgDataUrl) => {
                if (i > 0) {
                    doc.addPage();
                }

                const imgWidth = pageWidth - 2 * margin;
                const imgHeight = imgWidth * (content.clientHeight / content.clientWidth);
                const x = margin;
                const y = (pageHeight - imgHeight) / 2;

                doc.addImage(imgDataUrl, 'PNG', x, y, imgWidth, imgHeight, '', 'FAST');
            })
            .catch((error) => {
                console.error('Failed to convert slide to image:', error);
            });

        if (notes != undefined) {
            notes.style.margin = '0';
            const txtNotes = " " + getSlideNotesText(notes);
            const translatedResult = await translateText(txtNotes);
            const combinedNote = txtNotes + "\n\nTranslated text: \n\n " + translatedResult;

            doc.addPage();

            doc.text(combinedNote, 10, 10, {
                maxWidth: pageWidth - 20
            });
        }
    }

    doc.save('slides.pdf');
};
@spinfal
Copy link

spinfal commented Feb 22, 2026

absolutely goated

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