PK ! l1e e pdf_shuffle/__init__.pyfrom flask import Flask import os import json app = Flask(__name__) from .views import index, send_pdf from .util import open_browser_tab def init(filename, start=1, end=None, step=1, random=True, host='localhost', port=5000): """ :param filename: :param start: :param end: :param step: :param bool|list|tuple random: :param host: :param port: :return: """ os.environ.update({ 'FILENAME': filename, 'PAGE_START': str(start), 'PAGE_END': json.dumps(end), 'PAGE_STEP': str(step), 'PAGE_RANDOM': json.dumps(random), 'HOST': host, 'PORT': str(port) }) open_browser_tab('http://{}:{}/'.format(os.getenv('HOST'), os.getenv('PORT'))) app.run(host=os.getenv('HOST'), port=os.getenv('PORT')) def init_quiz(filename, start=2, end=None, step=2, random=True, host='localhost', port=5000): """ :param filename: :param start: :param end: :param step: :param bool|list|tuple random: :param host: :param port: :return: """ init(filename, start, end, step, random, host, port) PK ! ۿ pdf_shuffle/__main__.pyimport click import os from . import init @click.command() @click.argument('filename') @click.option('--start', default=1, envvar='PAGE_START') @click.option('--end', default=None, envvar='PAGE_END') @click.option('--step', default=1, envvar='PAGE_STEP') @click.option('--random/--no-random', default=True, envvar='PAGE_RANDOM') @click.option('--host', default='localhost', envvar='HOST') @click.option('--port', default=5000, envvar='PORT') def pdf_shuffle(filename, start, end, step, random, host, port): init(filename, start, end, step, random, host, port) def pdf_quiz(): os.environ.update({ 'PAGE_START': '2', 'PAGE_STEP': '2' }) pdf_shuffle() PK ! ssl pdf_shuffle/static/index.css* { margin: 0px; } body { width: 100%; min-width: 100%; } #nav-area { border: 1px solid #ccc; background-color: #f1f1f1; display: inline-table; width: 100%; } /* Style the buttons that are used to open the tab content */ #new-record, .page-button { background-color: inherit; border: none; outline: none; padding: 14px 16px; margin: 0px; transition: 0.3s; font-size: 17px; } .page-button:disabled { color: white; } #nav-page-button, #nav-page-button > *, #page-label > * { display: inherit; } #page-label > * { margin-left: 0.5em; margin-right: 0.5em; } #pdf-container { position: relative; overflow: scroll; } #pdf-area { position: absolute; height: auto; width: 100%; } #pdf-area:focus { outline: none; } PK ! .DT T pdf_shuffle/static/index.jslet pdfCache; const SCALING = 2; init(); document.getElementById('previous-all').onclick = ()=>{ config.current = config.start; renderPage(); } document.getElementById('previous').onclick = ()=>{ config.current--; renderPage(); } document.getElementById('next-all').onclick = ()=>{ config.current = config.end; renderPage(); } document.getElementById('next').onclick = ()=>{ config.current++; renderPage(); } document.getElementById('pdf-area').onclick = ()=>{ if(config.end && config.stepped < config.step && config.current < config.end){ config.current++; config.stepped++; renderPage(false); } else { config.stepped = 1; randomizePages(); } } document.body.addEventListener('keydown', (e)=>{ e = e || window.event; const keyPressed = e.which || e.keyCode; const key = { left: 37, // up: 38, right: 39, // down: 40, space: 32, backspace: 8, enter: 13 } switch (keyPressed) { case key.left: document.getElementById('previous').click(); break; case key.right: document.getElementById('next').click(); break; case key.space: case key.enter: document.getElementById('pdf-area').click(); break; case key.backspace: if(config.last && /(?:^|\/).*\.pdf/i.test(config.filename)){ config.current = config.last; renderPage(); } break; default: } }); window.addEventListener('resize', ()=>{ Object.assign(document.getElementById('pdf-container').style, getTrueWindowDimension()); }); function init(){ config.stepped = 1; config.userEnd = config.end; if(Array.isArray(config.random) && config.random.length > 0){ config.current = config.random[0] } else { config.current = config.start; } document.getElementById('title').innerHTML = config.filename; Object.assign(document.getElementById('pdf-container').style, getTrueWindowDimension()); randomizePages(); } function getTrueWindowDimension(){ return { height: (window.innerHeight - document.getElementById('nav-area').offsetHeight) + 'px', width: window.innerWidth + 'px' }; } function setPageNav(){ if(config.current >= config.step + config.start){ document.getElementById('previous-all').disabled = false; document.getElementById('previous').disabled = false; } else { document.getElementById('previous-all').disabled = true; document.getElementById('previous').disabled = true; } if((!config.end) || config.current <= config.end - config.step){ document.getElementById('next-all').disabled = false; document.getElementById('next').disabled = false; } else { document.getElementById('next-all').disabled = true; document.getElementById('next').disabled = true; } } async function randomizePages(){ if(!pdfCache || config.random === true || !(/(?:^|\/).*\.pdf/i.test(config.filename))){ await pdfjsLib.getDocument('/file?filename=' + encodeURIComponent(config.filename)) .then(pdf=>{ pdfCache = pdf; config.end = config.userEnd || pdfCache.numPages; document.getElementById('page-label-total').innerHTML = pdfCache.numPages; }); } config.last = config.current; if(config.random){ if(Array.isArray(config.random)){ config.current = config.random[Math.floor(Math.random() * config.random.length)]; } else { config.current = (Math.floor(Math.random() * (config.end - config.start + 1)/config.step) * config.step) + config.start; } } else { if((!config.end) || config.current <= config.end - config.step){ config.current++; } } if(config.current !== config.last){ renderPage(); } } function renderPage(resetStep){ if(resetStep !== false){ config.stepped = config.step; } if(pdfCache === undefined){ return; } pdfCache.getPage(config.current) .then(page=>{ console.log('Page', config.current); const canvas = document.getElementById('pdf-area'); const context = canvas.getContext('2d'); const viewport = page.getViewport(SCALING); const trueHeight = parseInt(getTrueWindowDimension().height); canvas.width = viewport.width; canvas.height = viewport.height; if(canvas.offsetHeight > trueHeight){ Object.assign(canvas.style, { top: '0', left: '50%', transform: 'translateX(-50%)' }); } else if (canvas.offsetHeight < trueHeight){ Object.assign(canvas.style, { top: '50%', left: '0', transform: 'translateY(-50%)' }); } if(viewport.height > viewport.width){ Object.assign(canvas.style, { height: 'auto', width: '100%' }); } else { Object.assign(canvas.style, { height: '100%', width: 'auto' }); } page.render({canvasContext: context, viewport: viewport}); document.getElementById('page-label-current').innerHTML = config.current; Object.assign(document.getElementById('pdf-container'), { scrollTop: 0, scrollLeft: 0 }); setPageNav(); canvas.focus(); }); } PK ! BB B pdf_shuffle/templates/index.html