From c1df87582d08202f53217b5de92b1bfc510446c6 Mon Sep 17 00:00:00 2001 From: caribaud Date: Fri, 26 May 2023 23:32:11 +0200 Subject: [PATCH 01/22] Change scrolling behaviour --- melpomene.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/melpomene.js b/melpomene.js index 04ac503..1ca0744 100644 --- a/melpomene.js +++ b/melpomene.js @@ -459,7 +459,19 @@ function handleKeyPress(key){ } -function handleMouseWhell(deltaY){ +function handleMouseWhell(event){ + + // Only handle scroll event if the target is the nav controls + // to avoid preventing page scrolling. + + // Do disable page scrolling when we do prev/next, though + + if (! READER_FRAME.contains(event.target)){ + return + } + + event.preventDefault() + event.stopPropagation() if (MOUSEWHELL_WAIT){ return @@ -470,7 +482,7 @@ function handleMouseWhell(deltaY){ }, MOUSEWHELL_MIN_DELAY) } - if (deltaY > 0) { + if (event.deltaY > 0) { moveReader(true, false) } @@ -497,5 +509,5 @@ addEventListener("keydown", (event) => { }); addEventListener("wheel", (event) => { - handleMouseWhell(event.deltaY) -}); + handleMouseWhell(event) +}, { passive:false }); From 350dd4bb0e30906387172c8fbc96940f251e1f0d Mon Sep 17 00:00:00 2001 From: caribaud Date: Sat, 27 May 2023 15:56:31 +0200 Subject: [PATCH 02/22] Fix width / height computation Closes #9 --- melpomene.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/melpomene.js b/melpomene.js index 1ca0744..a3a8e3c 100644 --- a/melpomene.js +++ b/melpomene.js @@ -180,11 +180,11 @@ function getPagesCount() { } function pageOriginalHeight(pageNumber) { - return READER_PAGES.children[pageNumber - 1].height + return READER_PAGES.children[pageNumber - 1].naturalHeight } function pageOriginalWidth(pageNumber) { - return READER_PAGES.children[pageNumber - 1].width + return READER_PAGES.children[pageNumber - 1].naturalWidth } function readerFrameRatio() { @@ -192,15 +192,15 @@ function readerFrameRatio() { } function pageRatio(pageNumber) { - return READER_PAGES.children[pageNumber - 1].width / READER_PAGES.children[pageNumber - 1].height + return READER_PAGES.children[pageNumber - 1].naturalWidth / READER_PAGES.children[pageNumber - 1].naturalHeight } function pageMaxHeight(){ let max_height = 0 for (var i = 0; i < READER_PAGES.children.length; i++) { - if(READER_PAGES.children[i].height > max_height){ - max_height = READER_PAGES.children[i].height + if(READER_PAGES.children[i].naturalHeight > max_height){ + max_height = READER_PAGES.children[i].naturalHeight } } @@ -217,7 +217,7 @@ function previousPagesWidth(pageNumber) { let totalWidth = 0 for (let idx = 0; idx < pageNumber - 1; idx++){ - totalWidth = totalWidth + READER_PAGES.children[idx].width + totalWidth = totalWidth + READER_PAGES.children[idx].naturalWidth } return totalWidth From 81be7d477b85099e11e96b97f70dbd5854d32d4b Mon Sep 17 00:00:00 2001 From: caribaud Date: Sat, 27 May 2023 15:58:42 +0200 Subject: [PATCH 03/22] Prevent external CSS img interferences Closes #10 --- melpomene.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/melpomene.css b/melpomene.css index daf6044..0e0f008 100644 --- a/melpomene.css +++ b/melpomene.css @@ -31,6 +31,11 @@ background-color: black; } +/* Reset images style to avoid external CSS interfering */ +#melpomene img { + all: initial; +} + #melpomene-content-frame { position: relative; flex: 1; From 5f8d8873b311348ced29a0d4119fb3b9c361128d Mon Sep 17 00:00:00 2001 From: caribaud Date: Sat, 27 May 2023 16:08:58 +0200 Subject: [PATCH 04/22] Warn about floating height/width and round them Closes #8 --- zooms_generator.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zooms_generator.py b/zooms_generator.py index e886218..c9d7241 100644 --- a/zooms_generator.py +++ b/zooms_generator.py @@ -40,8 +40,12 @@ def extract_zooms(src_folder): tree = ET.parse(svg_path) root = tree.getroot() - zooms[idx]["width"] = int(root.get("width")) - zooms[idx]["height"] = int(root.get("height")) + if "." in root.get("width"): + print(f"WARNING: file {svg_path} has a floating width, it will be rounded", file=sys.stderr) + zooms[idx]["width"] = round(float(root.get("width"))) + if "." in root.get("height"): + print(f"WARNING: file {svg_path} has a floating height, it will be rounded", file=sys.stderr) + zooms[idx]["height"] = round(float(root.get("height"))) for area in root.findall('.//{*}rect'): zooms[idx]["zooms"].append([ From 230abf08e85c5eca731c4d7df1b0dda8fbfa267d Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 4 Jun 2023 16:42:49 +0200 Subject: [PATCH 05/22] Adding eslint --- .gitignore | 4 ++++ eslint/Dockerfile | 11 +++++++++++ eslint/eslintrc.json | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 eslint/Dockerfile create mode 100644 eslint/eslintrc.json diff --git a/.gitignore b/.gitignore index 308caa5..0916cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ +# ESLINT report +eslint_report.html + +# Demo sources demos/src_highres demos/src_lowres diff --git a/eslint/Dockerfile b/eslint/Dockerfile new file mode 100644 index 0000000..000aeb9 --- /dev/null +++ b/eslint/Dockerfile @@ -0,0 +1,11 @@ +FROM debian:latest + +RUN apt-get update && apt-get install -y --no-install-recommends npm + +RUN npm install eslint --global + +COPY eslintrc.json /eslintrc.json + +ENTRYPOINT ["eslint", "--no-eslintrc"] + +CMD ["--help"] diff --git a/eslint/eslintrc.json b/eslint/eslintrc.json new file mode 100644 index 0000000..76a0ec4 --- /dev/null +++ b/eslint/eslintrc.json @@ -0,0 +1,34 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "eslint:all" + ], + "rules": { + "semi": "warn", + "spaced-comment": "warn", + "padded-blocks": ["warn", "never"], + "camelcase": "warn", + "multiline-comment-style": "off", + "max-len": "warn", + "prefer-template": "warn", + "object-curly-spacing" : ["warn", "always"], + "func-style": ["warn", "declaration"], + "key-spacing": "warn", + "one-var": ["warn", "never"], + "quotes": "warn", + "space-before-function-paren": ["warn", "never"], + "no-undefined": "off", + "strict": ["error", "global"], + "keyword-spacing": "warn", + "function-call-argument-newline": "warn", + "operator-assignment": "off", + "space-before-blocks": "warn", + "brace-style": ["warn", "allman", {"allowSingleLine": true}], + "function-call-argument-newline" : ["warn", "consistent"], + "function-paren-newline": ["warn", "consistent"], + "no-magic-numbers": ["error", {"ignore": [0,1,2,100]}] + } +} From 5f3060995bc3144444decb5ed16eeb0780f50682 Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 4 Jun 2023 12:54:21 +0200 Subject: [PATCH 06/22] Rework melpomene to respect newly added ESLINT This includes: + Removing trailling whitespaces + Adding missing const keywords + Fixing equality checks + Removing unused variables, functions, etc... + Adding missing let & const statements + Use strict + Correcting all names to use camelCase + Using semicolons everywhere + Use Allman style everywhere + Make comments headers uniform This also includes: + Fixing displayed version number --- melpomene.js | 799 +++++++++++++++++++++++++++++---------------------- 1 file changed, 451 insertions(+), 348 deletions(-) diff --git a/melpomene.js b/melpomene.js index a3a8e3c..266623f 100644 --- a/melpomene.js +++ b/melpomene.js @@ -2,60 +2,63 @@ /* Version 1.0.0_RC1 */ /* CC-BY-NC-SA : https://git.aribaud.net/caribaud/melpomene/ */ -//============ -// CONTROLS -//============ +"use strict"; -MOVE_NEXT = "ArrowRight" -MOVE_BACK = "ArrowLeft" -TOGGLE_FULLSCREEN = "F" -TOGGLE_PROGRESSBAR = "P" -TOGGLE_VIEW_MODE = "V" +// ============ +// CONTROLS +// ============ + +const MOVE_NEXT = "ArrowRight"; +const MOVE_BACK = "ArrowLeft"; +const TOGGLE_FULLSCREEN = "F"; +const TOGGLE_PROGRESSBAR = "P"; +const TOGGLE_VIEW_MODE = "V"; -//======================== -// NAVIGATION CONSTANTS -//======================== +// ======================== +// NAVIGATION CONSTANTS +// ======================== -PAGE_TRANSITION_SPEED = "1.5s" -MOUSEWHELL_MIN_DELAY = 50 -DELAY_BEFORE_HIDDING_CONTROLS = 4000; +const MOUSEWHELL_MIN_DELAY = 50; +const DELAY_BEFORE_HIDDING_CONTROLS = 4000; -//==================== -// STATES CONSTANTS -//==================== +// ==================== +// STATES CONSTANTS +// ==================== -MELPOMENE_VERSION = "1.0.0_RC1" +const MELPOMENE_VERSION = "1.0.0_UNSTABLE"; -READER_FRAME = document.getElementById("melpomene") -READER_CONTENT_FRAME = document.getElementById("melpomene-content-frame") -READER_PAGES = document.getElementById("melpomene-pages") -FOCUS_OVERLAY_HEIGHT = document.getElementById("melpomene-focus") -FOCUS_OVERLAY_WIDTH = document.getElementById("melpomene-focus-col") -HELP_CONTROLS = document.getElementById("melpomene-help-menu") -PROGRESS_BAR_CONTAINER = document.getElementById("melpomene-progress-container") -PROGRESS_BAR = document.getElementById("melpomene-progress-bar") -PROGRESS_BAR_PAGES = document.getElementById("melpomene-progress-sections") -VERSION_DISPLAY = document.getElementById("melpomene-version") +const READER_FRAME = document.getElementById("melpomene"); +const READER_CONTENT_FRAME = document.getElementById("melpomene-content-frame"); +const READER_PAGES = document.getElementById("melpomene-pages"); +const FOCUS_OVERLAY_HEIGHT = document.getElementById("melpomene-focus"); +const FOCUS_OVERLAY_WIDTH = document.getElementById("melpomene-focus-col"); +const HELP_CONTROLS = document.getElementById("melpomene-help-menu"); +const PROGRESS_BAR_CONTAINER = document.getElementById("melpomene-progress-container"); +const PROGRESS_BAR = document.getElementById("melpomene-progress-bar"); +const PROGRESS_BAR_PAGES = document.getElementById("melpomene-progress-sections"); +const VERSION_DISPLAY = document.getElementById("melpomene-version"); -//=========================== -// STATES GLOBAL VARIABLES -//=========================== +// =========================== +// STATES GLOBAL VARIABLES +// =========================== +var PAGES_ZOOMS; // The variable ZOOMS can either be defined by another JS file or contructed at init -if (typeof PAGES_ZOOMS == 'undefined') { - PAGES_ZOOMS = null +if (typeof PAGES_ZOOMS === 'undefined') +{ + PAGES_ZOOMS = null; } -CURRENT_ZOOM = 0 -CURRENT_PAGE = 1 -CURRENT_WIDTH = 0 -CURRENT_HEIGHT = 0 -CURRENT_X = 0 -CURRENT_Y = 0 +var CURRENT_ZOOM = 0; +var CURRENT_PAGE = 1; +var CURRENT_WIDTH = 0; +var CURRENT_HEIGHT = 0; +var CURRENT_X = 0; +var CURRENT_Y = 0; -IS_PAGE_MODE = false -MOUSEWHELL_WAIT = false +var IS_PAGE_MODE = false; +var MOUSEWHELL_WAIT = false; // ============= // UTILITIES @@ -64,360 +67,433 @@ MOUSEWHELL_WAIT = false // Zooms utilites // -------------- -function globalZoomScale(){ - - if (READER_PAGES.dataset.globalZoomScale != undefined){ - return parseFloat(READER_PAGES.dataset.globalZoomScale) +function globalZoomScale() +{ + if (READER_PAGES.dataset.globalZoomScale !== undefined) + { + return parseFloat(READER_PAGES.dataset.globalZoomScale); } - - return 1.0 + + return 1.0; } -function globalZoomOffsetX(){ - - if (READER_PAGES.dataset.globalZoomOffset != undefined){ - return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[0]) +function globalZoomOffsetX() +{ + if (READER_PAGES.dataset.globalZoomOffset !== undefined) + { + return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[0]); } - - return 0.0 + + return 0.0; } -function globalZoomOffsetY(){ - - if (READER_PAGES.dataset.globalZoomOffset != undefined){ - return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[1]) +function globalZoomOffsetY() +{ + if (READER_PAGES.dataset.globalZoomOffset !== undefined) + { + return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[1]); } - - return 0.0 + + return 0.0; } -function loadZoomsFromImgTagsIfRequired(){ - +function loadZoomsFromImgTagsIfRequired() +{ // Zooms may be defined by another JS file - if (PAGES_ZOOMS == null){ - - PAGES_ZOOMS = [] - + if (PAGES_ZOOMS === null) + { + PAGES_ZOOMS = []; + // parse the data-zooms of each img and and the page number info - for (var i = 0; i < READER_PAGES.children.length; i++) { - - zooms_raw_data = READER_PAGES.children[i].dataset.zooms - + for (let idx = 0; idx < READER_PAGES.children.length; idx += 1) + { + const zoomsRawData = READER_PAGES.children[idx].dataset.zooms; + // ';' separates zooms data, ',' separates values // We add the page number (adding 1 because of indexing) - zooms = zooms_raw_data.split(";").map( - zoom => [i + 1].concat( + const zooms = zoomsRawData.split(";").map( + zoom => [idx + 1].concat( zoom.split(',').map( value => parseFloat(value) ) ) - ) - - PAGES_ZOOMS = PAGES_ZOOMS.concat(zooms) - } - - } - -} + ); -function getFirstZoomOfPage(pageNumber){ - - for (var zoom_idx = 0; zoom_idx < PAGES_ZOOMS.length; zoom_idx++){ - if (PAGES_ZOOMS[zoom_idx][0] == pageNumber) { - return zoom_idx + PAGES_ZOOMS = PAGES_ZOOMS.concat(zooms); } } } -function getLastZoomOfPage(pageNumber){ - let res = null - - for (var zoom_idx = 0; zoom_idx < PAGES_ZOOMS.length; zoom_idx++){ - if (PAGES_ZOOMS[zoom_idx][0] == pageNumber) { - res = zoom_idx - } - - if (res != null && PAGES_ZOOMS[zoom_idx][0] != pageNumber) { - break +function getFirstZoomOfPage(pageNumber) +{ + for (let zoomIdx = 0; zoomIdx < PAGES_ZOOMS.length; zoomIdx += 1) + { + if (PAGES_ZOOMS[zoomIdx][0] === pageNumber) + { + return zoomIdx; } } - - return res } -function getZoomCountForPage(pageNumber) { - return PAGES_ZOOMS.filter(zoom => zoom[0] == pageNumber).length -} +function getLastZoomOfPage(pageNumber) +{ + let res = null; -function getCurrentZoomIndexForPage() { - previousZoomsCount = PAGES_ZOOMS.filter(zoom => zoom[0] < CURRENT_PAGE).length - return CURRENT_ZOOM - previousZoomsCount + 1 -} + for (let zoomIdx = 0; zoomIdx < PAGES_ZOOMS.length; zoomIdx += 1) + { + if (PAGES_ZOOMS[zoomIdx][0] === pageNumber) + { + res = zoomIdx; + } -function getReadingProgressPercent() { - progressPerPage = 1 / getPagesCount() - - if (IS_PAGE_MODE){ - return 100 * progressPerPage * CURRENT_PAGE + if (res !== null && PAGES_ZOOMS[zoomIdx][0] !== pageNumber) + { + break; + } } - - progressPerZoom = progressPerPage / getZoomCountForPage(CURRENT_PAGE) - - readingProgress = (CURRENT_PAGE - 1) * progressPerPage + getCurrentZoomIndexForPage() * progressPerZoom - - return 100 * readingProgress + + return res; } -function updateProgressBar(){ - PROGRESS_BAR.style.width = getReadingProgressPercent() + "%" +function getZoomCountForPage(pageNumber) +{ + return PAGES_ZOOMS.filter(zoom => zoom[0] === pageNumber).length; +} + +function getCurrentZoomIndexForPage() +{ + const previousZoomsCount = PAGES_ZOOMS.filter(zoom => zoom[0] < CURRENT_PAGE).length; + return CURRENT_ZOOM - previousZoomsCount + 1; +} + +function getReadingProgressPercent() +{ + const progressPerPage = 1 / getPagesCount(); + + if (IS_PAGE_MODE) + { + return 100 * progressPerPage * CURRENT_PAGE; + } + + const progressPerZoom = progressPerPage / getZoomCountForPage(CURRENT_PAGE); + + const readingProgress = (CURRENT_PAGE - 1) * progressPerPage + getCurrentZoomIndexForPage() * progressPerZoom; + + return 100 * readingProgress; +} + +function updateProgressBar() +{ + PROGRESS_BAR.style.width = getReadingProgressPercent() + "%"; } // Dimensions utilites // ------------------- -function getPagesCount() { - return READER_PAGES.childElementCount +function getPagesCount() +{ + return READER_PAGES.childElementCount; } -function pageOriginalHeight(pageNumber) { - return READER_PAGES.children[pageNumber - 1].naturalHeight +function pageOriginalHeight(pageNumber) +{ + return READER_PAGES.children[pageNumber - 1].naturalHeight; } -function pageOriginalWidth(pageNumber) { - return READER_PAGES.children[pageNumber - 1].naturalWidth +function pageOriginalWidth(pageNumber) +{ + return READER_PAGES.children[pageNumber - 1].naturalWidth; } -function readerFrameRatio() { - return READER_CONTENT_FRAME.clientWidth / READER_CONTENT_FRAME.clientHeight +function readerFrameRatio() +{ + return READER_CONTENT_FRAME.clientWidth / READER_CONTENT_FRAME.clientHeight; } -function pageRatio(pageNumber) { - return READER_PAGES.children[pageNumber - 1].naturalWidth / READER_PAGES.children[pageNumber - 1].naturalHeight +function pageRatio(pageNumber) +{ + return READER_PAGES.children[pageNumber - 1].naturalWidth / READER_PAGES.children[pageNumber - 1].naturalHeight; } -function pageMaxHeight(){ - let max_height = 0 - - for (var i = 0; i < READER_PAGES.children.length; i++) { - if(READER_PAGES.children[i].naturalHeight > max_height){ - max_height = READER_PAGES.children[i].naturalHeight +function pageMaxHeight() +{ + let maxHeight = 0; + + for (let i = 0; i < READER_PAGES.children.length; i += 1) + { + if(READER_PAGES.children[i].naturalHeight > maxHeight) + { + maxHeight = READER_PAGES.children[i].naturalHeight; } } - - return max_height + + return maxHeight; } -function pageVerticalOffset(pageNumber) { - return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2 +function pageVerticalOffset(pageNumber) +{ + return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2; } -function previousPagesWidth(pageNumber) { +function previousPagesWidth(pageNumber) +{ // The width of all previous pages relative to the provided index - - let totalWidth = 0 - - for (let idx = 0; idx < pageNumber - 1; idx++){ - totalWidth = totalWidth + READER_PAGES.children[idx].naturalWidth + + let totalWidth = 0; + + for (let idx = 0; idx < pageNumber - 1; idx += 1) + { + totalWidth += READER_PAGES.children[idx].naturalWidth; } - - return totalWidth + + return totalWidth; } // ========= // ACTIONS // ========= -function initReader(){ - loadZoomsFromImgTagsIfRequired() - moveReaderDisplayToZoom(0) +function initReader() +{ + VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION); + loadZoomsFromImgTagsIfRequired(); + moveReaderDisplayToZoom(0); + // Smoothly show pictures when they intersect with the viewport - let visibilityObserver = new IntersectionObserver((entries, observer) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - entry.target.style.opacity = 1 - entry.target.style.visibility = "visible" - } else { - entry.target.style.opacity = 0 - entry.target.style.visibility = "hidden" - } - }); - }, { root: READER_CONTENT_FRAME, rootMargin: "-10px" }); - - for (var i = 0; i < READER_PAGES.children.length; i++) { - let img = READER_PAGES.children[i]; - visibilityObserver.observe(img) - - PROGRESS_BAR_PAGES.appendChild(document.createElement("div")) + const visibilityObserver = new IntersectionObserver( + (entries, observer) => + { + entries.forEach((entry) => + { + if (entry.isIntersecting) + { + entry.target.style.opacity = 1; + entry.target.style.visibility = "visible"; + } + + else + { + entry.target.style.opacity = 0; + entry.target.style.visibility = "hidden"; + } + }); + }, + { root: READER_CONTENT_FRAME, rootMargin: "-10px" } + ); + + for (let i = 0; i < READER_PAGES.children.length; i += 1) + { + const img = READER_PAGES.children[i]; + visibilityObserver.observe(img); + + PROGRESS_BAR_PAGES.appendChild(document.createElement("div")); } - - READER_PAGES.style.display = "flex" - - setTimeout(() => { - READER_PAGES.hidden = false - }, "300") - - setTimeout(() => { - HELP_CONTROLS.style.opacity = null; - HELP_CONTROLS.style.transform = null; - }, DELAY_BEFORE_HIDDING_CONTROLS) + + READER_PAGES.style.display = "flex"; + + setTimeout( + () => { READER_PAGES.hidden = false }, + "300" + ); + + setTimeout( + () => + { + HELP_CONTROLS.style.opacity = null; + HELP_CONTROLS.style.transform = null; + }, + DELAY_BEFORE_HIDDING_CONTROLS + ); } -function moveReaderDisplayToArea(pageNumber, width, height, posx, posy){ - +function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) +{ // Keep original values for registering - o_width = width - o_height = height - o_posx = posx - o_posy = posy - + let width = oWidth; + let height = oHeight; + let posx = oPosx; + let posy = oPosy; + // Apply global offsets before scales if we are displaying a zoom // Pages display uses width & height = 0 - if (width != 0 || height != 0){ - width = width * globalZoomScale() - height = height * globalZoomScale() - posx = (posx + globalZoomOffsetX()) * globalZoomScale() - posy = (posy + globalZoomOffsetY()) * globalZoomScale() + if (width !== 0 || height !== 0) + { + width = width * globalZoomScale(); + height = height * globalZoomScale(); + posx = (posx + globalZoomOffsetX()) * globalZoomScale(); + posy = (posy + globalZoomOffsetY()) * globalZoomScale(); } - + // reduce width if offset sent us outside of page - if (posx < 0) { - width = width + posx - posx = 0 - } - if ((posx + width) > pageOriginalWidth(pageNumber)) { - width = pageOriginalWidth(pageNumber) - posx + if (posx < 0) + { + width = width + posx; + posx = 0; } + if ((posx + width) > pageOriginalWidth(pageNumber)) + { + width = pageOriginalWidth(pageNumber) - posx; + } + // reduce height if offset sent us outside of page - if (posy < 0) { - height = height + posy - posy = 0 - } - if ((posy + height) > pageOriginalHeight(pageNumber)) { - height = pageOriginalHeight(pageNumber) - posy + if (posy < 0) + { + height = height + posy; + posy = 0; } - + if ((posy + height) > pageOriginalHeight(pageNumber)) + { + height = pageOriginalHeight(pageNumber) - posy; + } + + // Align the top-left corner of the frame with the page - READER_PAGES.style.transform = "translate(-" + previousPagesWidth(pageNumber) + "px, -" + pageVerticalOffset(pageNumber) + "px )" - + READER_PAGES.style.transform = "translate(-" + previousPagesWidth(pageNumber) + "px, -" + pageVerticalOffset(pageNumber) + "px )"; + // Then move so the top-left point of the zoom match the frame top-left - READER_PAGES.style.transform = "translate(" + (- posx) + "px, " + (-posy) + "px )" + READER_PAGES.style.transform - + READER_PAGES.style.transform = "translate(" + (- posx) + "px, " + (-posy) + "px )" + READER_PAGES.style.transform; + // Then, scale so the zoom would fit the frame, and center the zoom - if (width == 0){ - width = pageOriginalWidth(pageNumber) + if (width === 0) + { + width = pageOriginalWidth(pageNumber); } - - if (height == 0){ - height = pageOriginalHeight(pageNumber) + + if (height === 0) + { + height = pageOriginalHeight(pageNumber); } - - zoomRatio = width / height - - if (readerFrameRatio() > zoomRatio) { + + const zoomRatio = width / height; + + if (readerFrameRatio() > zoomRatio) + { // Frame wider than zoom => scale so heights are the same, offset on x - var zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientHeight / height - - READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform - - var scaledWidth = width * zoomToFrameScaleFactor - var offset = (READER_CONTENT_FRAME.clientWidth - scaledWidth) / 2 - - READER_PAGES.style.transform = "translateX(" + offset + "px)" + READER_PAGES.style.transform - - updateFocusByWidth(scaledWidth) - } else { + const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientHeight / height; + + READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; + + const scaledWidth = width * zoomToFrameScaleFactor; + const offset = (READER_CONTENT_FRAME.clientWidth - scaledWidth) / 2; + + READER_PAGES.style.transform = "translateX(" + offset + "px)" + READER_PAGES.style.transform; + + updateFocusByWidth(scaledWidth); + } + + else + { // Frame narower than zoom => scale so left/right match, offset on y - var zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientWidth / width - - READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform - - var scaledHeight = height * zoomToFrameScaleFactor - var offset = (READER_CONTENT_FRAME.clientHeight - scaledHeight) / 2 - - READER_PAGES.style.transform = "translateY(" + offset + "px)" + READER_PAGES.style.transform - - updateFocusByHeight(scaledHeight) + const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientWidth / width; + + READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; + + const scaledHeight = height * zoomToFrameScaleFactor; + const offset = (READER_CONTENT_FRAME.clientHeight - scaledHeight) / 2; + + READER_PAGES.style.transform = "translateY(" + offset + "px)" + READER_PAGES.style.transform; + + updateFocusByHeight(scaledHeight); } - + // Use values before global offset / scale - CURRENT_PAGE = pageNumber - CURRENT_WIDTH = o_width - CURRENT_HEIGHT = o_height - CURRENT_X = o_posx - CURRENT_Y = o_posy + CURRENT_PAGE = pageNumber; + CURRENT_WIDTH = oWidth; + CURRENT_HEIGHT = oHeight; + CURRENT_X = oPosx; + CURRENT_Y = oPosy; } -function refreshReaderDisplay() { - moveReaderDisplayToArea(CURRENT_PAGE, CURRENT_WIDTH, CURRENT_HEIGHT, CURRENT_X, CURRENT_Y) +function refreshReaderDisplay() +{ + moveReaderDisplayToArea(CURRENT_PAGE, CURRENT_WIDTH, CURRENT_HEIGHT, CURRENT_X, CURRENT_Y); } -function moveReaderDisplayToPage(pageNumber) { - moveReaderDisplayToArea(pageNumber, 0, 0, 0, 0) +function moveReaderDisplayToPage(pageNumber) +{ + moveReaderDisplayToArea(pageNumber, 0, 0, 0, 0); } -function moveReaderDisplayToZoom(index) { - - moveReaderDisplayToArea(PAGES_ZOOMS[index][0], PAGES_ZOOMS[index][1], PAGES_ZOOMS[index][2], PAGES_ZOOMS[index][3], PAGES_ZOOMS[index][4]) - - CURRENT_ZOOM = index +function moveReaderDisplayToZoom(index) +{ + moveReaderDisplayToArea(PAGES_ZOOMS[index][0], PAGES_ZOOMS[index][1], PAGES_ZOOMS[index][2], PAGES_ZOOMS[index][3], PAGES_ZOOMS[index][4]); + + CURRENT_ZOOM = index; } -function updateFocusByWidth(width){ - FOCUS_OVERLAY_WIDTH.style.width = (width / READER_CONTENT_FRAME.clientWidth * 100) + "%" - FOCUS_OVERLAY_HEIGHT.style.height = "100%" +function updateFocusByWidth(width) +{ + FOCUS_OVERLAY_WIDTH.style.width = (width / READER_CONTENT_FRAME.clientWidth * 100) + "%"; + FOCUS_OVERLAY_HEIGHT.style.height = "100%"; } -function updateFocusByHeight(height){ - FOCUS_OVERLAY_WIDTH.style.width = "100%" - FOCUS_OVERLAY_HEIGHT.style.height = (height / READER_CONTENT_FRAME.clientHeight * 100) + "%" +function updateFocusByHeight(height) +{ + FOCUS_OVERLAY_WIDTH.style.width = "100%"; + FOCUS_OVERLAY_HEIGHT.style.height = (height / READER_CONTENT_FRAME.clientHeight * 100) + "%"; } -function toggleViewMode() { - if (IS_PAGE_MODE){ - if (CURRENT_ZOOM != null){ - moveReaderDisplayToZoom(CURRENT_ZOOM) - } else { - moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)) +function toggleViewMode() +{ + if (IS_PAGE_MODE) + { + if (CURRENT_ZOOM !== null) + { + moveReaderDisplayToZoom(CURRENT_ZOOM); } - IS_PAGE_MODE = false - } else { - moveReaderDisplayToPage(CURRENT_PAGE) - IS_PAGE_MODE = true + + else + { + moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)); + } + + IS_PAGE_MODE = false; } - updateProgressBar() + else + { + moveReaderDisplayToPage(CURRENT_PAGE); + IS_PAGE_MODE = true; + } + + updateProgressBar(); } -function moveReader(to_next) { - - if (IS_PAGE_MODE){ - if (to_next && CURRENT_PAGE < getPagesCount()) { - moveReaderDisplayToPage(CURRENT_PAGE + 1) - CURRENT_ZOOM = null +function moveReader(toNext) +{ + if (IS_PAGE_MODE) + { + if (toNext && CURRENT_PAGE < getPagesCount()) + { + moveReaderDisplayToPage(CURRENT_PAGE + 1); + CURRENT_ZOOM = null; } - - else if (!to_next && CURRENT_PAGE > 1) { - moveReaderDisplayToPage(CURRENT_PAGE - 1) - CURRENT_ZOOM = null - } - - } else { - - if (to_next && CURRENT_ZOOM < PAGES_ZOOMS.length - 1) { - moveReaderDisplayToZoom(CURRENT_ZOOM + 1) - } - - else if (!to_next && CURRENT_ZOOM > 0) { - moveReaderDisplayToZoom(CURRENT_ZOOM - 1) + + else if (!toNext && CURRENT_PAGE > 1) + { + moveReaderDisplayToPage(CURRENT_PAGE - 1); + CURRENT_ZOOM = null; } } - updateProgressBar() - + else + { + if (toNext && CURRENT_ZOOM < PAGES_ZOOMS.length - 1) + { + moveReaderDisplayToZoom(CURRENT_ZOOM + 1); + } + + else if (!toNext && CURRENT_ZOOM > 0) + { + moveReaderDisplayToZoom(CURRENT_ZOOM - 1); + } + } + + updateProgressBar(); } @@ -425,69 +501,89 @@ function moveReader(to_next) { // CALLBACKS // ============= -function handleKeyPress(key){ - - if (key == MOVE_NEXT) { - moveReader(true) +function handleKeyPress(key) +{ + if (key === MOVE_NEXT) + { + moveReader(true); } - - else if (key == MOVE_BACK) { - moveReader(false) + + else if (key === MOVE_BACK) + { + moveReader(false); } - - else if (key.toUpperCase() == TOGGLE_FULLSCREEN){ - if (document.fullscreenElement == null){ + + else if (key.toUpperCase() === TOGGLE_FULLSCREEN) + { + if (document.fullscreenElement === null) + { READER_FRAME.requestFullscreen(); - } else { - document.exitFullscreen(); } - } - - else if (key.toUpperCase() == TOGGLE_PROGRESSBAR){ - if (PROGRESS_BAR_CONTAINER.hidden == true) { - PROGRESS_BAR_CONTAINER.hidden = false - } else { - PROGRESS_BAR_CONTAINER.hidden = true + else + { + document.exitFullscreen(); } + } + + else if (key.toUpperCase() === TOGGLE_PROGRESSBAR) + { + if (PROGRESS_BAR_CONTAINER.hidden === true) + { + PROGRESS_BAR_CONTAINER.hidden = false; + } + + else + { + PROGRESS_BAR_CONTAINER.hidden = true; + } + refreshReaderDisplay(); } - - else if (key.toUpperCase() == TOGGLE_VIEW_MODE) { - toggleViewMode() - } + else if (key.toUpperCase() === TOGGLE_VIEW_MODE) + { + toggleViewMode(); + } } -function handleMouseWhell(event){ - +function handleMouseWhell(event) +{ // Only handle scroll event if the target is the nav controls // to avoid preventing page scrolling. - - // Do disable page scrolling when we do prev/next, though - - if (! READER_FRAME.contains(event.target)){ - return + + // Do disable page scrolling when we do prev/next, though + + if (! READER_FRAME.contains(event.target)) + { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if (MOUSEWHELL_WAIT) + { + return; } - event.preventDefault() - event.stopPropagation() - - if (MOUSEWHELL_WAIT){ - return - } else { - MOUSEWHELL_WAIT = true - setTimeout(() => { - MOUSEWHELL_WAIT = false - }, MOUSEWHELL_MIN_DELAY) + else + { + MOUSEWHELL_WAIT = true; + setTimeout( + () => { MOUSEWHELL_WAIT = false; }, + MOUSEWHELL_MIN_DELAY + ); } - - if (event.deltaY > 0) { - moveReader(true, false) + + if (event.deltaY > 0) + { + moveReader(true, false); } - - else { - moveReader(false, false) + + else + { + moveReader(false, false); } } @@ -495,19 +591,26 @@ function handleMouseWhell(event){ // INIT // ====== -window.addEventListener("load", (event) => { - VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION) - initReader() -}); +window.addEventListener( + "load", + (event) => { initReader() } +); -addEventListener("resize", (event) => { - refreshReaderDisplay(); -}); +addEventListener( + "resize", + (event) => { refreshReaderDisplay() } +); -addEventListener("keydown", (event) => { - handleKeyPress(event.key, event.shiftKey) -}); +addEventListener( + "keydown", + (event) => + { + handleKeyPress(event.key, event.shiftKey) + } +); -addEventListener("wheel", (event) => { - handleMouseWhell(event) -}, { passive:false }); +addEventListener( + "wheel", + (event) => { handleMouseWhell(event) }, + { passive:false } +); From c8451c07aa75f5ec56c92d9bbb559ee78f3e7760 Mon Sep 17 00:00:00 2001 From: Christian Aribaud Date: Sun, 4 Jun 2023 20:46:43 +0200 Subject: [PATCH 07/22] Adding info about ESLint in README.md --- README.md | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b8a99d2..c162532 100644 --- a/README.md +++ b/README.md @@ -25,16 +25,19 @@ flowchart TB ``` Melpomene is mainly one JS file and one CSS file. You only need to include them in you web page. They are : - + `melpomene.js` - + `melpomene.css` + ++ `melpomene.js` + ++ `melpomene.css` The JS files expect you to write some very specific HTML tags to be able to work. To simplify things, you only need to copy-paste the content of `melpomene.html` into your own page and change a few things : + + You must duplicate the `img` tag for each of you comic page and : + set `url` to the actual URL of your page + set `height` and `width` to the actual image sizes + set `data-zooms` with the zooms information, like so : `, , , ; ...` - + example : `` + + example : `` Because doing this by hand would be very tedious, Melpomene comes with an helper script that allows generating that HTML for you from SVGs. @@ -45,7 +48,7 @@ The following limitations are known and will be improved upon : + Mobile support is currently limited + There are some performences issues -# How to setup Melpomene ? +# How to use Melpomene ? ## Defining the zooms @@ -55,21 +58,21 @@ To do so, you can use your favorite SVG editor. If you don't have one, [Inkscape To create the zooms for a comic page, what you need to do is : 1. Open your comic page in your editor (make sure to keep the image's original size when importing!) - * If your software ask, there is no need to actually import the image, you only need to link it. + * If your software ask, there is no need to actually import the image, you only need to link it. 2. Create a simple rectangle over each zoom you want, in the order you want them to show up - * You can set the rectangle's color to be translucent so you can still see the page underneath them! - * If you want to change the zoom order, you can change their order in the layer view of your SVG tool if they support it + * You can set the rectangle's color to be translucent so you can still see the page underneath them! + * If you want to change the zoom order, you can change their order in the layer view of your SVG tool if they support it 3. Once you are done, save the SGV - ## Generating the HTML files Once the SVG for your pages are done, put them in one folder. Then, you can run the zoom generator. You need to open a terminal and then run : + + `python zooms_generator.py html -p -e ` + For example, if your comic pages are hosted at `static/comic/page_x.jpg`, the svg must be named `page_x.svg` - and you must run `python zooms_generator.py html -p /static/comic/ -e jpg` + and you must run `python zooms_generator.py html -p /static/comic/ -e jpg` + It will generate the following `img` tag : `` The pages need to be in alphabetical order! It assumes the first page is page 1, the next one is page 2, etc.. @@ -89,6 +92,24 @@ If you need to do some global scaling / offset of all zooms in HTML (if for exam + If they become greater than the page size, they get clamped to the page size and width / height get reduced to compensate + `data-global-zoom-scale=""` : scale all positions / sizes by this factor +# Developpement + +## Setting up quality checking for JS + + Regarding JS, quality checking is done using [eslint](https://eslint.org/). + +The configuration file is `eslint/eslintrc.json`. + +To setup eslint, you can either install it on your system reading it's documentation, or use the provided Dockerfile to run it. This requires [docker](https://www.docker.com/). + +To do so, assuming you are using linux, after installing docker, you can run from this repository root: + ++ `docker build -t melpomene-eslint eslint/`, once + ++ `docker run -v .:/melpomene:rw -w /melpomene --user $(id -u):$(id -g) melpomene-eslint`, every time you want to run the analysis + +You can now open `eslint_report.html` to see the result. + # Credits -Most examples and the documentation of Melpomene uses illustrations from David "Deevad" Revoy's "Pepper & Carrot" webcomic, which is published under CC-BY 4.0. Full licence [here](https://www.peppercarrot.com/en/license/index.html). +Most examples and the documentation of Melpomene uses illustrations from David "Deevad" Revoy's "Pepper & Carrot" webcomic, which is published under CC-BY 4.0. Full licence [here](https://www.peppercarrot.com/en/license/index.html).  From ca0f9f4e599778c15370a962fc624c7b78487dc5 Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 4 Jun 2023 20:57:51 +0200 Subject: [PATCH 08/22] Fixing Dockerfile to match with Readme.md --- eslint/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eslint/Dockerfile b/eslint/Dockerfile index 000aeb9..a369c63 100644 --- a/eslint/Dockerfile +++ b/eslint/Dockerfile @@ -6,6 +6,6 @@ RUN npm install eslint --global COPY eslintrc.json /eslintrc.json -ENTRYPOINT ["eslint", "--no-eslintrc"] +WORKDIR melpomene -CMD ["--help"] +CMD ["eslint", "--no-eslintrc", "-c", "eslint/eslintrc.json", "-f", "html", "-o", "eslint_report.html", "melpomene.js"] From f87f6c75f595a30749eefe51dc55baec994bbcbc Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 4 Jun 2023 21:37:56 +0200 Subject: [PATCH 09/22] Fixing unused functions and params --- eslint/eslintrc.json | 4 +++- melpomene.js | 37 ++++++------------------------------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/eslint/eslintrc.json b/eslint/eslintrc.json index 76a0ec4..5fd6db2 100644 --- a/eslint/eslintrc.json +++ b/eslint/eslintrc.json @@ -29,6 +29,8 @@ "brace-style": ["warn", "allman", {"allowSingleLine": true}], "function-call-argument-newline" : ["warn", "consistent"], "function-paren-newline": ["warn", "consistent"], - "no-magic-numbers": ["error", {"ignore": [0,1,2,100]}] + "no-magic-numbers": ["error", {"ignore": [0,1,2,100]}], + "quote-props": ["warn", "as-needed"], + "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}] } } diff --git a/melpomene.js b/melpomene.js index 266623f..8689592 100644 --- a/melpomene.js +++ b/melpomene.js @@ -135,26 +135,6 @@ function getFirstZoomOfPage(pageNumber) } } -function getLastZoomOfPage(pageNumber) -{ - let res = null; - - for (let zoomIdx = 0; zoomIdx < PAGES_ZOOMS.length; zoomIdx += 1) - { - if (PAGES_ZOOMS[zoomIdx][0] === pageNumber) - { - res = zoomIdx; - } - - if (res !== null && PAGES_ZOOMS[zoomIdx][0] !== pageNumber) - { - break; - } - } - - return res; -} - function getZoomCountForPage(pageNumber) { return PAGES_ZOOMS.filter(zoom => zoom[0] === pageNumber).length; @@ -210,11 +190,6 @@ function readerFrameRatio() return READER_CONTENT_FRAME.clientWidth / READER_CONTENT_FRAME.clientHeight; } -function pageRatio(pageNumber) -{ - return READER_PAGES.children[pageNumber - 1].naturalWidth / READER_PAGES.children[pageNumber - 1].naturalHeight; -} - function pageMaxHeight() { let maxHeight = 0; @@ -262,7 +237,7 @@ function initReader() // Smoothly show pictures when they intersect with the viewport const visibilityObserver = new IntersectionObserver( - (entries, observer) => + (entries, _observer) => { entries.forEach((entry) => { @@ -593,24 +568,24 @@ function handleMouseWhell(event) window.addEventListener( "load", - (event) => { initReader() } + (_event) => { initReader(); } ); addEventListener( "resize", - (event) => { refreshReaderDisplay() } + (_event) => { refreshReaderDisplay(); } ); addEventListener( "keydown", (event) => { - handleKeyPress(event.key, event.shiftKey) + handleKeyPress(event.key, event.shiftKey); } ); addEventListener( "wheel", - (event) => { handleMouseWhell(event) }, - { passive:false } + (event) => { handleMouseWhell(event); }, + { passive: false } ); From c6f88e8d85658cba6e782285670931e963ba9906 Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 4 Jun 2023 21:38:56 +0200 Subject: [PATCH 10/22] fix trailling whitespace --- melpomene.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/melpomene.js b/melpomene.js index 8689592..87a73ab 100644 --- a/melpomene.js +++ b/melpomene.js @@ -231,7 +231,7 @@ function previousPagesWidth(pageNumber) function initReader() { VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION); - + loadZoomsFromImgTagsIfRequired(); moveReaderDisplayToZoom(0); @@ -246,7 +246,7 @@ function initReader() entry.target.style.opacity = 1; entry.target.style.visibility = "visible"; } - + else { entry.target.style.opacity = 0; @@ -307,7 +307,7 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) width = width + posx; posx = 0; } - + if ((posx + width) > pageOriginalWidth(pageNumber)) { width = pageOriginalWidth(pageNumber) - posx; @@ -319,7 +319,7 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) height = height + posy; posy = 0; } - + if ((posy + height) > pageOriginalHeight(pageNumber)) { height = pageOriginalHeight(pageNumber) - posy; @@ -359,7 +359,7 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) updateFocusByWidth(scaledWidth); } - + else { // Frame narower than zoom => scale so left/right match, offset on y @@ -420,15 +420,15 @@ function toggleViewMode() { moveReaderDisplayToZoom(CURRENT_ZOOM); } - + else { moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)); } - + IS_PAGE_MODE = false; } - + else { moveReaderDisplayToPage(CURRENT_PAGE); @@ -454,7 +454,7 @@ function moveReader(toNext) CURRENT_ZOOM = null; } } - + else { if (toNext && CURRENT_ZOOM < PAGES_ZOOMS.length - 1) @@ -494,7 +494,7 @@ function handleKeyPress(key) { READER_FRAME.requestFullscreen(); } - + else { document.exitFullscreen(); @@ -507,12 +507,12 @@ function handleKeyPress(key) { PROGRESS_BAR_CONTAINER.hidden = false; } - + else { PROGRESS_BAR_CONTAINER.hidden = true; } - + refreshReaderDisplay(); } @@ -541,7 +541,7 @@ function handleMouseWhell(event) { return; } - + else { MOUSEWHELL_WAIT = true; From 7299157521c9de5c2bf8b8ad3ef44b50499e1ef3 Mon Sep 17 00:00:00 2001 From: caribaud Date: Mon, 5 Jun 2023 00:16:02 +0200 Subject: [PATCH 11/22] new round of fixing eslint findings --- eslint/eslintrc.json | 4 +++- melpomene.js | 44 ++++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/eslint/eslintrc.json b/eslint/eslintrc.json index 5fd6db2..92436b8 100644 --- a/eslint/eslintrc.json +++ b/eslint/eslintrc.json @@ -31,6 +31,8 @@ "function-paren-newline": ["warn", "consistent"], "no-magic-numbers": ["error", {"ignore": [0,1,2,100]}], "quote-props": ["warn", "as-needed"], - "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}] + "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}], + "max-len" : ["warn", {"code": 88}], + "capitalized-comments": "off" } } diff --git a/melpomene.js b/melpomene.js index 87a73ab..be4f664 100644 --- a/melpomene.js +++ b/melpomene.js @@ -327,10 +327,10 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) // Align the top-left corner of the frame with the page - READER_PAGES.style.transform = "translate(-" + previousPagesWidth(pageNumber) + "px, -" + pageVerticalOffset(pageNumber) + "px )"; + READER_PAGES.style.transform = `translate(-${previousPagesWidth(pageNumber)}px, -${pageVerticalOffset(pageNumber)}px)`; // Then move so the top-left point of the zoom match the frame top-left - READER_PAGES.style.transform = "translate(" + (- posx) + "px, " + (-posy) + "px )" + READER_PAGES.style.transform; + READER_PAGES.style.transform = `translate(${-posx}px, ${-posy}px) ${READER_PAGES.style.transform}`; // Then, scale so the zoom would fit the frame, and center the zoom if (width === 0) @@ -350,12 +350,12 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) // Frame wider than zoom => scale so heights are the same, offset on x const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientHeight / height; - READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; + READER_PAGES.style.transform = `scale(${zoomToFrameScaleFactor}) ${READER_PAGES.style.transform}`; const scaledWidth = width * zoomToFrameScaleFactor; const offset = (READER_CONTENT_FRAME.clientWidth - scaledWidth) / 2; - READER_PAGES.style.transform = "translateX(" + offset + "px)" + READER_PAGES.style.transform; + READER_PAGES.style.transform = `translateX(${offset}px) ${READER_PAGES.style.transform}`; updateFocusByWidth(scaledWidth); } @@ -365,12 +365,12 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) // Frame narower than zoom => scale so left/right match, offset on y const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientWidth / width; - READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; + READER_PAGES.style.transform = `scale(${zoomToFrameScaleFactor}) ${READER_PAGES.style.transform}`; const scaledHeight = height * zoomToFrameScaleFactor; const offset = (READER_CONTENT_FRAME.clientHeight - scaledHeight) / 2; - READER_PAGES.style.transform = "translateY(" + offset + "px)" + READER_PAGES.style.transform; + READER_PAGES.style.transform = `translateY(${offset}px) ${READER_PAGES.style.transform}"`; updateFocusByHeight(scaledHeight); } @@ -402,28 +402,28 @@ function moveReaderDisplayToZoom(index) function updateFocusByWidth(width) { - FOCUS_OVERLAY_WIDTH.style.width = (width / READER_CONTENT_FRAME.clientWidth * 100) + "%"; + FOCUS_OVERLAY_WIDTH.style.width = `${width / READER_CONTENT_FRAME.clientWidth * 100}%`; FOCUS_OVERLAY_HEIGHT.style.height = "100%"; } function updateFocusByHeight(height) { FOCUS_OVERLAY_WIDTH.style.width = "100%"; - FOCUS_OVERLAY_HEIGHT.style.height = (height / READER_CONTENT_FRAME.clientHeight * 100) + "%"; + FOCUS_OVERLAY_HEIGHT.style.height = `${height / READER_CONTENT_FRAME.clientHeight * 100}%`; } function toggleViewMode() { if (IS_PAGE_MODE) { - if (CURRENT_ZOOM !== null) + if (CURRENT_ZOOM === null) { - moveReaderDisplayToZoom(CURRENT_ZOOM); + moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)); } else { - moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)); + moveReaderDisplayToZoom(CURRENT_ZOOM); } IS_PAGE_MODE = false; @@ -453,8 +453,11 @@ function moveReader(toNext) moveReaderDisplayToPage(CURRENT_PAGE - 1); CURRENT_ZOOM = null; } + + updateProgressBar(); } + // Zoom mode else { if (toNext && CURRENT_ZOOM < PAGES_ZOOMS.length - 1) @@ -466,9 +469,9 @@ function moveReader(toNext) { moveReaderDisplayToZoom(CURRENT_ZOOM - 1); } - } - updateProgressBar(); + updateProgressBar(); + } } @@ -529,7 +532,7 @@ function handleMouseWhell(event) // Do disable page scrolling when we do prev/next, though - if (! READER_FRAME.contains(event.target)) + if (!READER_FRAME.contains(event.target)) { return; } @@ -542,14 +545,11 @@ function handleMouseWhell(event) return; } - else - { - MOUSEWHELL_WAIT = true; - setTimeout( - () => { MOUSEWHELL_WAIT = false; }, - MOUSEWHELL_MIN_DELAY - ); - } + MOUSEWHELL_WAIT = true; + setTimeout( + () => { MOUSEWHELL_WAIT = false; }, + MOUSEWHELL_MIN_DELAY + ); if (event.deltaY > 0) { From f1cfb326d530f40c10bfe2117b4430d25dad689e Mon Sep 17 00:00:00 2001 From: caribaud Date: Mon, 5 Jun 2023 00:17:23 +0200 Subject: [PATCH 12/22] Fix declaration order --- melpomene.js | 239 +++++++++++++++++++++++++-------------------------- 1 file changed, 119 insertions(+), 120 deletions(-) diff --git a/melpomene.js b/melpomene.js index be4f664..d76678f 100644 --- a/melpomene.js +++ b/melpomene.js @@ -64,6 +64,63 @@ var MOUSEWHELL_WAIT = false; // UTILITIES // ============= +// Dimensions utilites +// ------------------- + +function getPagesCount() +{ + return READER_PAGES.childElementCount; +} + +function pageOriginalHeight(pageNumber) +{ + return READER_PAGES.children[pageNumber - 1].naturalHeight; +} + +function pageOriginalWidth(pageNumber) +{ + return READER_PAGES.children[pageNumber - 1].naturalWidth; +} + +function readerFrameRatio() +{ + return READER_CONTENT_FRAME.clientWidth / READER_CONTENT_FRAME.clientHeight; +} + +function pageMaxHeight() +{ + let maxHeight = 0; + + for (let i = 0; i < READER_PAGES.children.length; i += 1) + { + if(READER_PAGES.children[i].naturalHeight > maxHeight) + { + maxHeight = READER_PAGES.children[i].naturalHeight; + } + } + + return maxHeight; +} + +function pageVerticalOffset(pageNumber) +{ + return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2; +} + +function previousPagesWidth(pageNumber) +{ + // The width of all previous pages relative to the provided index + + let totalWidth = 0; + + for (let idx = 0; idx < pageNumber - 1; idx += 1) + { + totalWidth += READER_PAGES.children[idx].naturalWidth; + } + + return totalWidth; +} + // Zooms utilites // -------------- @@ -167,121 +224,21 @@ function updateProgressBar() PROGRESS_BAR.style.width = getReadingProgressPercent() + "%"; } -// Dimensions utilites -// ------------------- - -function getPagesCount() -{ - return READER_PAGES.childElementCount; -} - -function pageOriginalHeight(pageNumber) -{ - return READER_PAGES.children[pageNumber - 1].naturalHeight; -} - -function pageOriginalWidth(pageNumber) -{ - return READER_PAGES.children[pageNumber - 1].naturalWidth; -} - -function readerFrameRatio() -{ - return READER_CONTENT_FRAME.clientWidth / READER_CONTENT_FRAME.clientHeight; -} - -function pageMaxHeight() -{ - let maxHeight = 0; - - for (let i = 0; i < READER_PAGES.children.length; i += 1) - { - if(READER_PAGES.children[i].naturalHeight > maxHeight) - { - maxHeight = READER_PAGES.children[i].naturalHeight; - } - } - - return maxHeight; -} - -function pageVerticalOffset(pageNumber) -{ - return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2; -} - -function previousPagesWidth(pageNumber) -{ - // The width of all previous pages relative to the provided index - - let totalWidth = 0; - - for (let idx = 0; idx < pageNumber - 1; idx += 1) - { - totalWidth += READER_PAGES.children[idx].naturalWidth; - } - - return totalWidth; -} - // ========= // ACTIONS // ========= -function initReader() +function updateFocusByWidth(width) { - VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION); - - loadZoomsFromImgTagsIfRequired(); - moveReaderDisplayToZoom(0); - - // Smoothly show pictures when they intersect with the viewport - const visibilityObserver = new IntersectionObserver( - (entries, _observer) => - { - entries.forEach((entry) => - { - if (entry.isIntersecting) - { - entry.target.style.opacity = 1; - entry.target.style.visibility = "visible"; - } - - else - { - entry.target.style.opacity = 0; - entry.target.style.visibility = "hidden"; - } - }); - }, - { root: READER_CONTENT_FRAME, rootMargin: "-10px" } - ); - - for (let i = 0; i < READER_PAGES.children.length; i += 1) - { - const img = READER_PAGES.children[i]; - visibilityObserver.observe(img); - - PROGRESS_BAR_PAGES.appendChild(document.createElement("div")); - } - - READER_PAGES.style.display = "flex"; - - setTimeout( - () => { READER_PAGES.hidden = false }, - "300" - ); - - setTimeout( - () => - { - HELP_CONTROLS.style.opacity = null; - HELP_CONTROLS.style.transform = null; - }, - DELAY_BEFORE_HIDDING_CONTROLS - ); + FOCUS_OVERLAY_WIDTH.style.width = `${width / READER_CONTENT_FRAME.clientWidth * 100}%`; + FOCUS_OVERLAY_HEIGHT.style.height = "100%"; } +function updateFocusByHeight(height) +{ + FOCUS_OVERLAY_WIDTH.style.width = "100%"; + FOCUS_OVERLAY_HEIGHT.style.height = `${height / READER_CONTENT_FRAME.clientHeight * 100}%`; +} function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) { @@ -400,18 +357,6 @@ function moveReaderDisplayToZoom(index) CURRENT_ZOOM = index; } -function updateFocusByWidth(width) -{ - FOCUS_OVERLAY_WIDTH.style.width = `${width / READER_CONTENT_FRAME.clientWidth * 100}%`; - FOCUS_OVERLAY_HEIGHT.style.height = "100%"; -} - -function updateFocusByHeight(height) -{ - FOCUS_OVERLAY_WIDTH.style.width = "100%"; - FOCUS_OVERLAY_HEIGHT.style.height = `${height / READER_CONTENT_FRAME.clientHeight * 100}%`; -} - function toggleViewMode() { if (IS_PAGE_MODE) @@ -474,6 +419,60 @@ function moveReader(toNext) } } +function initReader() +{ + VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION); + + loadZoomsFromImgTagsIfRequired(); + moveReaderDisplayToZoom(0); + + // Smoothly show pictures when they intersect with the viewport + const visibilityObserver = new IntersectionObserver( + (entries, _observer) => + { + entries.forEach((entry) => + { + if (entry.isIntersecting) + { + entry.target.style.opacity = 1; + entry.target.style.visibility = "visible"; + } + + else + { + entry.target.style.opacity = 0; + entry.target.style.visibility = "hidden"; + } + }); + }, + { root: READER_CONTENT_FRAME, rootMargin: "-10px" } + ); + + for (let i = 0; i < READER_PAGES.children.length; i += 1) + { + const img = READER_PAGES.children[i]; + visibilityObserver.observe(img); + + PROGRESS_BAR_PAGES.appendChild(document.createElement("div")); + } + + READER_PAGES.style.display = "flex"; + + setTimeout( + () => { READER_PAGES.hidden = false }, + "300" + ); + + setTimeout( + () => + { + HELP_CONTROLS.style.opacity = null; + HELP_CONTROLS.style.transform = null; + }, + DELAY_BEFORE_HIDDING_CONTROLS + ); +} + // ============= // CALLBACKS From 5a1987f77b1e573178b2f250359c3078d3d03346 Mon Sep 17 00:00:00 2001 From: caribaud Date: Mon, 5 Jun 2023 00:20:32 +0200 Subject: [PATCH 13/22] single quote -> double quote --- melpomene.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/melpomene.js b/melpomene.js index d76678f..4ad7a55 100644 --- a/melpomene.js +++ b/melpomene.js @@ -45,7 +45,7 @@ const VERSION_DISPLAY = document.getElementById("melpomene-version"); var PAGES_ZOOMS; // The variable ZOOMS can either be defined by another JS file or contructed at init -if (typeof PAGES_ZOOMS === 'undefined') +if (typeof PAGES_ZOOMS === "undefined") { PAGES_ZOOMS = null; } @@ -138,7 +138,7 @@ function globalZoomOffsetX() { if (READER_PAGES.dataset.globalZoomOffset !== undefined) { - return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[0]); + return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(",")[0]); } return 0.0; @@ -148,7 +148,7 @@ function globalZoomOffsetY() { if (READER_PAGES.dataset.globalZoomOffset !== undefined) { - return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[1]); + return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(",")[1]); } return 0.0; @@ -166,11 +166,11 @@ function loadZoomsFromImgTagsIfRequired() { const zoomsRawData = READER_PAGES.children[idx].dataset.zooms; - // ';' separates zooms data, ',' separates values + // ";" separates zooms data, "," separates values // We add the page number (adding 1 because of indexing) const zooms = zoomsRawData.split(";").map( zoom => [idx + 1].concat( - zoom.split(',').map( + zoom.split(",").map( value => parseFloat(value) ) ) From b12cf2c4f1be477c321498ace524bcd141b17533 Mon Sep 17 00:00:00 2001 From: caribaud Date: Mon, 5 Jun 2023 00:40:25 +0200 Subject: [PATCH 14/22] new eslint fixes run --- eslint/eslintrc.json | 3 ++- melpomene.js | 55 +++++++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/eslint/eslintrc.json b/eslint/eslintrc.json index 92436b8..77aaba5 100644 --- a/eslint/eslintrc.json +++ b/eslint/eslintrc.json @@ -33,6 +33,7 @@ "quote-props": ["warn", "as-needed"], "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}], "max-len" : ["warn", {"code": 88}], - "capitalized-comments": "off" + "capitalized-comments": "off", + "operator-linebreak": ["warn", "before"] } } diff --git a/melpomene.js b/melpomene.js index 4ad7a55..8572c8c 100644 --- a/melpomene.js +++ b/melpomene.js @@ -91,11 +91,11 @@ function pageMaxHeight() { let maxHeight = 0; - for (let i = 0; i < READER_PAGES.children.length; i += 1) + for (let pageIdx = 0; pageIdx < READER_PAGES.children.length; pageIdx += 1) { - if(READER_PAGES.children[i].naturalHeight > maxHeight) + if (READER_PAGES.children[pageIdx].naturalHeight > maxHeight) { - maxHeight = READER_PAGES.children[i].naturalHeight; + maxHeight = READER_PAGES.children[pageIdx].naturalHeight; } } @@ -104,7 +104,7 @@ function pageMaxHeight() function pageVerticalOffset(pageNumber) { - return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2; + return (pageMaxHeight() - pageOriginalHeight(pageNumber)) / 2; } function previousPagesWidth(pageNumber) @@ -169,9 +169,9 @@ function loadZoomsFromImgTagsIfRequired() // ";" separates zooms data, "," separates values // We add the page number (adding 1 because of indexing) const zooms = zoomsRawData.split(";").map( - zoom => [idx + 1].concat( + (zoom) => [idx + 1].concat( zoom.split(",").map( - value => parseFloat(value) + (value) => parseFloat(value) ) ) ); @@ -190,16 +190,18 @@ function getFirstZoomOfPage(pageNumber) return zoomIdx; } } + + return undefined; } function getZoomCountForPage(pageNumber) { - return PAGES_ZOOMS.filter(zoom => zoom[0] === pageNumber).length; + return PAGES_ZOOMS.filter((zoom) => zoom[0] === pageNumber).length; } function getCurrentZoomIndexForPage() { - const previousZoomsCount = PAGES_ZOOMS.filter(zoom => zoom[0] < CURRENT_PAGE).length; + const previousZoomsCount = PAGES_ZOOMS.filter((zoom) => zoom[0] < CURRENT_PAGE).length; return CURRENT_ZOOM - previousZoomsCount + 1; } @@ -214,14 +216,16 @@ function getReadingProgressPercent() const progressPerZoom = progressPerPage / getZoomCountForPage(CURRENT_PAGE); - const readingProgress = (CURRENT_PAGE - 1) * progressPerPage + getCurrentZoomIndexForPage() * progressPerZoom; + + let readingProgress = (CURRENT_PAGE - 1) * progressPerPage; + readingProgress += getCurrentZoomIndexForPage() * progressPerZoom; return 100 * readingProgress; } function updateProgressBar() { - PROGRESS_BAR.style.width = getReadingProgressPercent() + "%"; + PROGRESS_BAR.style.width = `${getReadingProgressPercent()}%`; } // ========= @@ -265,7 +269,7 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) posx = 0; } - if ((posx + width) > pageOriginalWidth(pageNumber)) + if (posx + width > pageOriginalWidth(pageNumber)) { width = pageOriginalWidth(pageNumber) - posx; } @@ -277,7 +281,7 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) posy = 0; } - if ((posy + height) > pageOriginalHeight(pageNumber)) + if (posy + height > pageOriginalHeight(pageNumber)) { height = pageOriginalHeight(pageNumber) - posy; } @@ -342,7 +346,13 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) function refreshReaderDisplay() { - moveReaderDisplayToArea(CURRENT_PAGE, CURRENT_WIDTH, CURRENT_HEIGHT, CURRENT_X, CURRENT_Y); + moveReaderDisplayToArea( + CURRENT_PAGE, + CURRENT_WIDTH, + CURRENT_HEIGHT, + CURRENT_X, + CURRENT_Y + ); } function moveReaderDisplayToPage(pageNumber) @@ -352,7 +362,13 @@ function moveReaderDisplayToPage(pageNumber) function moveReaderDisplayToZoom(index) { - moveReaderDisplayToArea(PAGES_ZOOMS[index][0], PAGES_ZOOMS[index][1], PAGES_ZOOMS[index][2], PAGES_ZOOMS[index][3], PAGES_ZOOMS[index][4]); + moveReaderDisplayToArea( + PAGES_ZOOMS[index][0], + PAGES_ZOOMS[index][1], + PAGES_ZOOMS[index][2], + PAGES_ZOOMS[index][3], + PAGES_ZOOMS[index][4] + ); CURRENT_ZOOM = index; } @@ -445,12 +461,15 @@ function initReader() } }); }, - { root: READER_CONTENT_FRAME, rootMargin: "-10px" } + { + root: READER_CONTENT_FRAME, + rootMargin: "-10px" + } ); - for (let i = 0; i < READER_PAGES.children.length; i += 1) + for (let pageIndex = 0; pageIndex < READER_PAGES.children.length; pageIndex += 1) { - const img = READER_PAGES.children[i]; + const img = READER_PAGES.children[pageIndex]; visibilityObserver.observe(img); PROGRESS_BAR_PAGES.appendChild(document.createElement("div")); @@ -459,7 +478,7 @@ function initReader() READER_PAGES.style.display = "flex"; setTimeout( - () => { READER_PAGES.hidden = false }, + () => { READER_PAGES.hidden = false; }, "300" ); From b3fddef4e06db7031037f3ada7979cd78d7ee8db Mon Sep 17 00:00:00 2001 From: Kronk Date: Sun, 18 Jun 2023 17:05:36 +0200 Subject: [PATCH 15/22] Added script to update version in headers and variables. --- header_version_updater.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 header_version_updater.py diff --git a/header_version_updater.py b/header_version_updater.py new file mode 100644 index 0000000..1c558bd --- /dev/null +++ b/header_version_updater.py @@ -0,0 +1,45 @@ +import re +from pathlib import Path + +version = input("New version = ").strip() + +js_file = Path("melpomene.js") +css_file = Path("melpomene.css") +js_css_match = r"(?<=/\* Version ).*(?= \*/)" + +js_variable_match = r"(?<=const MELPOMENE_VERSION = \").*(?=\";)" + +html_file = Path("melpomene.html") +demo_high_res_file = Path("demos/pepper_and_carrot_e35_highres.html") +demo_low_res_file = Path("demos/pepper_and_carrot_e35_lowres.html") +html_match = r"(?<=)" + +zoom_generator_file = Path("zooms_generator.py") +zoom_generator_match = r"(?<=# Version ).*(?=$)" + + +def replace_version(version, file_path, matcher): + with open(file=file_path, mode="r", encoding="UTF8") as file: + file_data = file.read() + + file_data = re.sub(matcher, version, file_data) + + with open(file=file_path, mode="w", encoding="UTF8") as file: + file.write(file_data) + + +if re.match(r"[.a-zA-Z\ \-0-9]{1,30}", version): + replace_version(version, js_file, js_css_match) + replace_version(version, js_file, js_variable_match) + + replace_version(version, css_file, js_css_match) + + replace_version(version, html_file, html_match) + replace_version(version, demo_high_res_file, html_match) + replace_version(version, demo_low_res_file, html_match) + + replace_version(version, zoom_generator_file, zoom_generator_match) + + print("Done") +else: + print("Input is not valid : only use letters, numbers, spaces, dots and dashes") From 21e17a294e3345097b42db55d1110a6a1389fd8e Mon Sep 17 00:00:00 2001 From: caribaud Date: Sun, 11 Jun 2023 09:51:47 +0200 Subject: [PATCH 16/22] more corrections --- eslint/eslintrc.json | 3 ++- melpomene.js | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/eslint/eslintrc.json b/eslint/eslintrc.json index 77aaba5..445108f 100644 --- a/eslint/eslintrc.json +++ b/eslint/eslintrc.json @@ -34,6 +34,7 @@ "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}], "max-len" : ["warn", {"code": 88}], "capitalized-comments": "off", - "operator-linebreak": ["warn", "before"] + "operator-linebreak": ["warn", "before"], + "max-lines": "off" } } diff --git a/melpomene.js b/melpomene.js index 8572c8c..567b92e 100644 --- a/melpomene.js +++ b/melpomene.js @@ -39,26 +39,36 @@ const PROGRESS_BAR = document.getElementById("melpomene-progress-bar"); const PROGRESS_BAR_PAGES = document.getElementById("melpomene-progress-sections"); const VERSION_DISPLAY = document.getElementById("melpomene-version"); +// ==================== +// INDEX CONSTANTS +// ==================== + +const ZOOM_PAGE_INDEX = 0; +const ZOOM_WIDTH_INDEX = 1; +const ZOOM_HEIGHT_INDEX = 2; +const ZOOM_X_INDEX = 3; +const ZOOM_Y_INDEX = 4; + // =========================== // STATES GLOBAL VARIABLES // =========================== -var PAGES_ZOOMS; +let PAGES_ZOOMS; // The variable ZOOMS can either be defined by another JS file or contructed at init if (typeof PAGES_ZOOMS === "undefined") { PAGES_ZOOMS = null; } -var CURRENT_ZOOM = 0; -var CURRENT_PAGE = 1; -var CURRENT_WIDTH = 0; -var CURRENT_HEIGHT = 0; -var CURRENT_X = 0; -var CURRENT_Y = 0; +let CURRENT_ZOOM = 0; +let CURRENT_PAGE = 1; +let CURRENT_WIDTH = 0; +let CURRENT_HEIGHT = 0; +let CURRENT_X = 0; +let CURRENT_Y = 0; -var IS_PAGE_MODE = false; -var MOUSEWHELL_WAIT = false; +let IS_PAGE_MODE = false; +let MOUSEWHELL_WAIT = false; // ============= // UTILITIES @@ -360,17 +370,17 @@ function moveReaderDisplayToPage(pageNumber) moveReaderDisplayToArea(pageNumber, 0, 0, 0, 0); } -function moveReaderDisplayToZoom(index) +function moveReaderDisplayToZoom(zoomIdx) { moveReaderDisplayToArea( - PAGES_ZOOMS[index][0], - PAGES_ZOOMS[index][1], - PAGES_ZOOMS[index][2], - PAGES_ZOOMS[index][3], - PAGES_ZOOMS[index][4] + PAGES_ZOOMS[zoomIdx][ZOOM_PAGE_INDEX], + PAGES_ZOOMS[zoomIdx][ZOOM_WIDTH_INDEX], + PAGES_ZOOMS[zoomIdx][ZOOM_HEIGHT_INDEX], + PAGES_ZOOMS[zoomIdx][ZOOM_X_INDEX], + PAGES_ZOOMS[zoomIdx][ZOOM_Y_INDEX] ); - CURRENT_ZOOM = index; + CURRENT_ZOOM = zoomIdx; } function toggleViewMode() From cb3c17c5dbfba1b5c54462413400d8ce85e8808c Mon Sep 17 00:00:00 2001 From: Kronk Date: Sat, 24 Jun 2023 23:35:42 +0200 Subject: [PATCH 17/22] Added pipenv files to offer a consistent python environment. Includes Python version, with black and prospector in the dev packages. --- Pipfile | 13 ++ Pipfile.lock | 509 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 522 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..813cc3f --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] +black = "*" +prospector = {extras = ["with_mypy"], version = "*"} + +[requires] +python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..3ffc5b6 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,509 @@ +{ + "_meta": { + "hash": { + "sha256": "6bf84a05ccc0682985bf11d77db01419dde589c614d97f59ca2bac4c4b43c80f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": {}, + "develop": { + "astroid": { + "hashes": [ + "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324", + "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f" + ], + "markers": "python_full_version >= '3.7.2'", + "version": "==2.15.5" + }, + "black": { + "hashes": [ + "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5", + "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915", + "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326", + "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940", + "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b", + "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30", + "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c", + "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c", + "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab", + "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27", + "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2", + "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961", + "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9", + "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb", + "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70", + "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331", + "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2", + "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266", + "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d", + "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6", + "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b", + "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925", + "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8", + "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4", + "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3" + ], + "index": "pypi", + "version": "==23.3.0" + }, + "click": { + "hashes": [ + "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.3" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "platform_system == 'Windows'", + "version": "==0.4.6" + }, + "dill": { + "hashes": [ + "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0", + "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373" + ], + "markers": "python_version >= '3.11'", + "version": "==0.3.6" + }, + "dodgy": { + "hashes": [ + "sha256:28323cbfc9352139fdd3d316fa17f325cc0e9ac74438cbba51d70f9b48f86c3a", + "sha256:51f54c0fd886fa3854387f354b19f429d38c04f984f38bc572558b703c0542a6" + ], + "version": "==0.2.1" + }, + "flake8": { + "hashes": [ + "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", + "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==5.0.4" + }, + "flake8-polyfill": { + "hashes": [ + "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9", + "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda" + ], + "version": "==1.0.2" + }, + "gitdb": { + "hashes": [ + "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a", + "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.10" + }, + "gitpython": { + "hashes": [ + "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573", + "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.31" + }, + "isort": { + "hashes": [ + "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", + "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==5.12.0" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", + "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", + "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", + "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", + "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", + "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", + "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", + "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", + "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", + "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", + "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", + "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", + "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", + "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", + "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", + "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", + "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", + "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", + "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", + "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", + "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", + "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", + "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", + "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", + "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", + "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", + "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", + "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", + "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", + "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", + "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", + "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", + "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", + "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", + "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", + "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.0" + }, + "mccabe": { + "hashes": [ + "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", + "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" + ], + "markers": "python_version >= '3.6'", + "version": "==0.7.0" + }, + "mypy": { + "hashes": [ + "sha256:0cf0ca95e4b8adeaf07815a78b4096b65adf64ea7871b39a2116c19497fcd0dd", + "sha256:0f98973e39e4a98709546a9afd82e1ffcc50c6ec9ce6f7870f33ebbf0bd4f26d", + "sha256:19d42b08c7532d736a7e0fb29525855e355fa51fd6aef4f9bbc80749ff64b1a2", + "sha256:210fe0f39ec5be45dd9d0de253cb79245f0a6f27631d62e0c9c7988be7152965", + "sha256:3b1b5c875fcf3e7217a3de7f708166f641ca154b589664c44a6fd6d9f17d9e7e", + "sha256:3f2b353eebef669529d9bd5ae3566905a685ae98b3af3aad7476d0d519714758", + "sha256:50f65f0e9985f1e50040e603baebab83efed9eb37e15a22a4246fa7cd660f981", + "sha256:53c2a1fed81e05ded10a4557fe12bae05b9ecf9153f162c662a71d924d504135", + "sha256:5a0ee54c2cb0f957f8a6f41794d68f1a7e32b9968675ade5846f538504856d42", + "sha256:62bf18d97c6b089f77f0067b4e321db089d8520cdeefc6ae3ec0f873621c22e5", + "sha256:653863c75f0dbb687d92eb0d4bd9fe7047d096987ecac93bb7b1bc336de48ebd", + "sha256:67242d5b28ed0fa88edd8f880aed24da481929467fdbca6487167cb5e3fd31ff", + "sha256:6ba9a69172abaa73910643744d3848877d6aac4a20c41742027dcfd8d78f05d9", + "sha256:6c34d43e3d54ad05024576aef28081d9d0580f6fa7f131255f54020eb12f5352", + "sha256:7461469e163f87a087a5e7aa224102a30f037c11a096a0ceeb721cb0dce274c8", + "sha256:94a81b9354545123feb1a99b960faeff9e1fa204fce47e0042335b473d71530d", + "sha256:a0b2e0da7ff9dd8d2066d093d35a169305fc4e38db378281fce096768a3dbdbf", + "sha256:a34eed094c16cad0f6b0d889811592c7a9b7acf10d10a7356349e325d8704b4f", + "sha256:a3af348e0925a59213244f28c7c0c3a2c2088b4ba2fe9d6c8d4fbb0aba0b7d05", + "sha256:b4c734d947e761c7ceb1f09a98359dd5666460acbc39f7d0a6b6beec373c5840", + "sha256:bba57b4d2328740749f676807fcf3036e9de723530781405cc5a5e41fc6e20de", + "sha256:ca33ab70a4aaa75bb01086a0b04f0ba8441e51e06fc57e28585176b08cad533b", + "sha256:de1e7e68148a213036276d1f5303b3836ad9a774188961eb2684eddff593b042", + "sha256:f051ca656be0c179c735a4c3193f307d34c92fdc4908d44fd4516fbe8b10567d", + "sha256:f5984a8d13d35624e3b235a793c814433d810acba9eeefe665cdfed3d08bc3af", + "sha256:f7a5971490fd4a5a436e143105a1f78fa8b3fe95b30fff2a77542b4f3227a01f" + ], + "version": "==1.4.0" + }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "pathspec": { + "hashes": [ + "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", + "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.1" + }, + "pep8-naming": { + "hashes": [ + "sha256:5d9f1056cb9427ce344e98d1a7f5665710e2f20f748438e308995852cfa24164", + "sha256:f3b4a5f9dd72b991bf7d8e2a341d2e1aa3a884a769b5aaac4f56825c1763bf3a" + ], + "version": "==0.10.0" + }, + "platformdirs": { + "hashes": [ + "sha256:b0cabcb11063d21a0b261d557acb0a9d2126350e63b70cdf7db6347baea456dc", + "sha256:ca9ed98ce73076ba72e092b23d3c93ea6c4e186b3f1c3dad6edd98ff6ffcca2e" + ], + "markers": "python_version >= '3.7'", + "version": "==3.8.0" + }, + "prospector": { + "extras": [ + "with_mypy" + ], + "hashes": [ + "sha256:3bfe103c28bb821cca84926ca31357fbfd32405e4bf8c34ca2e55885684557e4", + "sha256:cc8f09e79bdd32247edddf05b666940e88ad96338a84f5717b1e8c0678337821" + ], + "index": "pypi", + "version": "==1.10.2" + }, + "pycodestyle": { + "hashes": [ + "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", + "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b" + ], + "markers": "python_version >= '3.6'", + "version": "==2.9.1" + }, + "pydocstyle": { + "hashes": [ + "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019", + "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1" + ], + "markers": "python_version >= '3.6'", + "version": "==6.3.0" + }, + "pyflakes": { + "hashes": [ + "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", + "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3" + ], + "markers": "python_version >= '3.6'", + "version": "==2.5.0" + }, + "pylint": { + "hashes": [ + "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1", + "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c" + ], + "markers": "python_full_version >= '3.7.2'", + "version": "==2.17.4" + }, + "pylint-celery": { + "hashes": [ + "sha256:41e32094e7408d15c044178ea828dd524beedbdbe6f83f712c5e35bde1de4beb" + ], + "version": "==0.3" + }, + "pylint-django": { + "hashes": [ + "sha256:0ac090d106c62fe33782a1d01bda1610b761bb1c9bf5035ced9d5f23a13d8591", + "sha256:56b12b6adf56d548412445bd35483034394a1a94901c3f8571980a13882299d5" + ], + "version": "==2.5.3" + }, + "pylint-flask": { + "hashes": [ + "sha256:f4d97de2216bf7bfce07c9c08b166e978fe9f2725de2a50a9845a97de7e31517" + ], + "version": "==0.6" + }, + "pylint-plugin-utils": { + "hashes": [ + "sha256:b3d43e85ab74c4f48bb46ae4ce771e39c3a20f8b3d56982ab17aa73b4f98d535", + "sha256:ce48bc0516ae9415dd5c752c940dfe601b18fe0f48aa249f2386adfa95a004dd" + ], + "markers": "python_full_version >= '3.6.2'", + "version": "==0.7" + }, + "pyyaml": { + "hashes": [ + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0" + }, + "requirements-detector": { + "hashes": [ + "sha256:3642cd7a5b261d79536c36bb7ecacf2adabd902d2e0e42bfb2ba82515da10501", + "sha256:d7c60493bf166da3dd59de0e6cb25765e0e32a1931aeae92614034e5786d0bd0" + ], + "markers": "python_version >= '3.7' and python_version < '4.0'", + "version": "==1.2.2" + }, + "semver": { + "hashes": [ + "sha256:2a23844ba1647362c7490fe3995a86e097bb590d16f0f32dfc383008f19e4cdf", + "sha256:9ec78c5447883c67b97f98c3b6212796708191d22e4ad30f4570f840171cbce1" + ], + "markers": "python_version >= '3.7'", + "version": "==3.0.1" + }, + "setoptconf-tmp": { + "hashes": [ + "sha256:76035d5cd1593d38b9056ae12d460eca3aaa34ad05c315b69145e138ba80a745", + "sha256:e0480addd11347ba52f762f3c4d8afa3e10ad0affbc53e3ffddc0ca5f27d5778" + ], + "version": "==0.3.1" + }, + "smmap": { + "hashes": [ + "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", + "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", + "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" + ], + "version": "==2.2.0" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, + "tomlkit": { + "hashes": [ + "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171", + "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.8" + }, + "typing-extensions": { + "hashes": [ + "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26", + "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5" + ], + "markers": "python_version >= '3.7'", + "version": "==4.6.3" + }, + "wrapt": { + "hashes": [ + "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", + "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", + "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", + "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", + "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", + "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", + "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", + "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", + "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", + "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", + "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", + "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", + "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", + "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", + "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", + "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", + "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", + "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", + "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", + "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", + "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", + "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", + "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", + "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", + "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", + "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", + "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", + "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", + "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", + "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", + "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", + "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", + "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", + "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", + "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", + "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", + "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", + "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", + "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", + "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", + "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", + "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", + "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", + "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", + "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", + "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", + "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", + "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", + "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", + "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", + "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", + "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", + "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", + "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", + "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", + "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", + "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", + "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", + "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", + "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", + "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", + "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", + "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", + "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", + "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", + "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", + "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", + "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", + "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", + "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", + "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", + "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", + "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", + "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", + "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" + ], + "markers": "python_version >= '3.11'", + "version": "==1.15.0" + } + } +} From 3d7428e76fb97f4f5b5fc53d101a8d4dc1d91fc1 Mon Sep 17 00:00:00 2001 From: Christian Aribaud Date: Sun, 25 Jun 2023 09:20:06 +0200 Subject: [PATCH 18/22] Adding info regarding python quality checking --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c162532..16a3653 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ If you need to do some global scaling / offset of all zooms in HTML (if for exam ## Setting up quality checking for JS - Regarding JS, quality checking is done using [eslint](https://eslint.org/). +Regarding JS, quality checking is done using [eslint](https://eslint.org/). The configuration file is `eslint/eslintrc.json`. @@ -110,6 +110,23 @@ To do so, assuming you are using linux, after installing docker, you can run fro You can now open `eslint_report.html` to see the result. +## Setting up quality checking for Python + +Regarding Python, quality checking is done using [prospector](https://prospector.landscape.io/en/master/) using [mypy](https://mypy.readthedocs.io/en/stable/) as an additional checker. +Auto-formating is done using [Black](https://pypi.org/project/black/) + +Dependencies are managed not using `pip` but [`pipenv`](https://pipenv.pypa.io/en/latest/). + +To setup prospector, you need to run: + ++ Only once, in melpomene's root folder: + + Install pipenv: `pip install pipenv` + + Install melpomene's root folder: `pipenv install --dev` ++ Every time to run the quality checking: + + `pipenv shell` + + `prospector -s veryhigh -w mypy --max-line-length 88 .` + + `black .` + # Credits Most examples and the documentation of Melpomene uses illustrations from David "Deevad" Revoy's "Pepper & Carrot" webcomic, which is published under CC-BY 4.0. Full licence [here](https://www.peppercarrot.com/en/license/index.html).  From 7e52c5a532e8a1634f98244c62518404bb9019ab Mon Sep 17 00:00:00 2001 From: Christian Aribaud Date: Sun, 25 Jun 2023 09:20:38 +0200 Subject: [PATCH 19/22] Running black on python files --- zooms_generator.py | 120 +++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 48 deletions(-) diff --git a/zooms_generator.py b/zooms_generator.py index c9d7241..f31ff3d 100644 --- a/zooms_generator.py +++ b/zooms_generator.py @@ -18,60 +18,66 @@ def extract_zooms(src_folder): folder = Path(src_folder) zooms = {} - + max_width = 0 max_height = 0 - + idx = 0 for svg_path in folder.glob("*.svg"): - idx += 1 - + print(f"page {idx} : {svg_path.name}") - + zooms[idx] = { "name": svg_path.stem, "width": 0, "height": 0, "zooms": [], } - + tree = ET.parse(svg_path) root = tree.getroot() if "." in root.get("width"): - print(f"WARNING: file {svg_path} has a floating width, it will be rounded", file=sys.stderr) + print( + f"WARNING: file {svg_path} has a floating width, it will be rounded", + file=sys.stderr, + ) zooms[idx]["width"] = round(float(root.get("width"))) if "." in root.get("height"): - print(f"WARNING: file {svg_path} has a floating height, it will be rounded", file=sys.stderr) + print( + f"WARNING: file {svg_path} has a floating height, it will be rounded", + file=sys.stderr, + ) zooms[idx]["height"] = round(float(root.get("height"))) - - for area in root.findall('.//{*}rect'): - zooms[idx]["zooms"].append([ - float(area.get("width")), - float(area.get("height")), - float(area.get("x")), - float(area.get("y")), - ]) + + for area in root.findall(".//{*}rect"): + zooms[idx]["zooms"].append( + [ + float(area.get("width")), + float(area.get("height")), + float(area.get("x")), + float(area.get("y")), + ] + ) return zooms, max_width, max_height def write_json_or_js(zooms, dest_file, is_js): - with open(dest_file, "w") as data_file: - if is_js: data_file.write("PAGES_ZOOMS = ") data_file.write("[\n") first_coma_skiped = False for page_idx in sorted(zooms.keys()): for zoom in zooms[page_idx]["zooms"]: - - if zoom[2] < 0 or zoom[3] < 0 : - print(f"WARNING: negative pos x / pos y in page {page_idx} for zoom {zoom} (is the rectangle flipped?)") - + if zoom[2] < 0 or zoom[3] < 0: + print( + f"WARNING: negative pos x / pos y in page {page_idx} for zoom {zoom} (is the rectangle flipped?)" + ) + if first_coma_skiped: data_file.write(",\n") else: @@ -81,68 +87,86 @@ def write_json_or_js(zooms, dest_file, is_js): def write_html(zooms, dest_file, pages_width, pages_height, prefix, extention): - img_tags = "" for page_idx in sorted(zooms.keys()): img_url = f"{prefix}{zooms[page_idx]['name']}.{extention}" - zoom_html_data = [','.join([str(zoom) for zoom in page_zooms]) for page_zooms in zooms[page_idx]["zooms"]] - zoom_html_str = ';'.join(zoom_html_data) - img_tags = img_tags + f' \n' - + zoom_html_data = [ + ",".join([str(zoom) for zoom in page_zooms]) + for page_zooms in zooms[page_idx]["zooms"] + ] + zoom_html_str = ";".join(zoom_html_data) + img_tags = ( + img_tags + + f' \n' + ) + img_tags = img_tags.strip() - + with open(HTML_TEMPLATE) as template_file, open(dest_file, "w") as data_file: - data = template_file.read().replace(HTML_TO_REPLACE, img_tags) - + data_file.write(data) def generate_argparse(): - """ Generate Melpomene's generator input parser""" - + """Generate Melpomene's generator input parser""" + parser = argparse.ArgumentParser( description="Helper that can generate JSON / JS / HTML files for Melpomene webcomic reader" ) - - parser.add_argument("output_format", choices=["html", "json", "js"], help="The type of output to generate") + + parser.add_argument( + "output_format", + choices=["html", "json", "js"], + help="The type of output to generate", + ) parser.add_argument("svg_folders", help="Path of the folder containing the SVGs") - parser.add_argument("-o", metavar="dest_file", help="Where to write the generator output to") - parser.add_argument("-p", default="", metavar="img_url_prefix", help="What to prefix the URL of the images when using HTML format.") - parser.add_argument("-e", default="png", metavar="img_ext", help="What extention to use in the URL of the images when using HTML format.") - + parser.add_argument( + "-o", metavar="dest_file", help="Where to write the generator output to" + ) + parser.add_argument( + "-p", + default="", + metavar="img_url_prefix", + help="What to prefix the URL of the images when using HTML format.", + ) + parser.add_argument( + "-e", + default="png", + metavar="img_ext", + help="What extention to use in the URL of the images when using HTML format.", + ) + return parser if __name__ == "__main__": - args = generate_argparse().parse_args() - - + # Get the final outout name output = None - + if not args.o: output = "melpomene_data" else: output = args.o - + if args.output_format == "html" and not output.endswith(".html"): output += ".html" - + elif args.output_format == "json" and not output.endswith(".json"): output += ".json" - + elif args.output_format == "js" and not output.endswith(".js"): output += ".js" - + zooms, max_width, max_height = extract_zooms(args.svg_folders) if args.output_format == "html": write_html(zooms, output, max_width, max_height, args.p, args.e) - + elif args.output_format == "json": write_json_or_js(zooms, output, False) - + elif args.output_format == "js": write_json_or_js(zooms, output, True) From ce00b327bbdde6fb15db1114c8f7cd893a79460b Mon Sep 17 00:00:00 2001 From: Christian Aribaud Date: Sun, 25 Jun 2023 10:37:59 +0200 Subject: [PATCH 20/22] fixing prospector findings in zoom generator --- zooms_generator.py | 93 ++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/zooms_generator.py b/zooms_generator.py index f31ff3d..6d60ee7 100644 --- a/zooms_generator.py +++ b/zooms_generator.py @@ -3,10 +3,10 @@ # CC-BY-NC-SA https://git.aribaud.net/caribaud/melpomene/ import sys -import re -import xml.etree.ElementTree as ET -import argparse - +from argparse import ArgumentParser +from xml.etree import ElementTree +from xml.etree.ElementTree import Element +from typing import Any from pathlib import Path @@ -14,13 +14,19 @@ HTML_TEMPLATE = Path(__file__).parent / "melpomene.html" HTML_TO_REPLACE = "" -def extract_zooms(src_folder): +def get_val_has_str(elem: Element, attrib: str, filepath: str | Path) -> str: + value = elem.get(attrib) + + if value is None: + sys.exit(f"Attribute '{attrib}' is not valid in file {filepath}") + + return str(value) + + +def extract_zooms(src_folder) -> dict[int, Any]: folder = Path(src_folder) - zooms = {} - - max_width = 0 - max_height = 0 + pages_zooms: dict[int, Any] = {} idx = 0 @@ -29,44 +35,52 @@ def extract_zooms(src_folder): print(f"page {idx} : {svg_path.name}") - zooms[idx] = { + # Setting up default values + pages_zooms[idx] = { "name": svg_path.stem, "width": 0, "height": 0, "zooms": [], } - tree = ET.parse(svg_path) + tree = ElementTree.parse(svg_path) root = tree.getroot() - if "." in root.get("width"): + width = get_val_has_str(root, "width", svg_path) + height = get_val_has_str(root, "height", svg_path) + + if "." in width: print( f"WARNING: file {svg_path} has a floating width, it will be rounded", file=sys.stderr, ) - zooms[idx]["width"] = round(float(root.get("width"))) - if "." in root.get("height"): + pages_zooms[idx]["width"] = round(float(width)) + + if "." in height: print( f"WARNING: file {svg_path} has a floating height, it will be rounded", file=sys.stderr, ) - zooms[idx]["height"] = round(float(root.get("height"))) + pages_zooms[idx]["height"] = round(float(height)) + zooms = [] for area in root.findall(".//{*}rect"): - zooms[idx]["zooms"].append( + zooms.append( [ - float(area.get("width")), - float(area.get("height")), - float(area.get("x")), - float(area.get("y")), + float(get_val_has_str(area, "width", svg_path)), + float(get_val_has_str(area, "height", svg_path)), + float(get_val_has_str(area, "x", svg_path)), + float(get_val_has_str(area, "y", svg_path)), ] ) - return zooms, max_width, max_height + pages_zooms[idx]["zooms"] = zooms + + return pages_zooms -def write_json_or_js(zooms, dest_file, is_js): - with open(dest_file, "w") as data_file: +def write_json_or_js(zooms, dest_file, is_js) -> None: + with open(dest_file, "w", encoding="UTF-8") as data_file: if is_js: data_file.write("PAGES_ZOOMS = ") data_file.write("[\n") @@ -75,7 +89,8 @@ def write_json_or_js(zooms, dest_file, is_js): for zoom in zooms[page_idx]["zooms"]: if zoom[2] < 0 or zoom[3] < 0: print( - f"WARNING: negative pos x / pos y in page {page_idx} for zoom {zoom} (is the rectangle flipped?)" + f"WARNING: negative pos x / pos y in page {page_idx} for " + f"zoom {zoom} (is the rectangle flipped?)" ) if first_coma_skiped: @@ -86,7 +101,7 @@ def write_json_or_js(zooms, dest_file, is_js): data_file.write("\n]\n") -def write_html(zooms, dest_file, pages_width, pages_height, prefix, extention): +def write_html(zooms, dest_file, prefix, extention) -> None: img_tags = "" for page_idx in sorted(zooms.keys()): img_url = f"{prefix}{zooms[page_idx]['name']}.{extention}" @@ -97,22 +112,30 @@ def write_html(zooms, dest_file, pages_width, pages_height, prefix, extention): zoom_html_str = ";".join(zoom_html_data) img_tags = ( img_tags - + f' \n' + + " " + + f'\n' ) img_tags = img_tags.strip() - with open(HTML_TEMPLATE) as template_file, open(dest_file, "w") as data_file: + with open(HTML_TEMPLATE, "r", encoding="UTF-8") as template_file, open( + dest_file, "w", encoding="UTF-8" + ) as data_file: data = template_file.read().replace(HTML_TO_REPLACE, img_tags) data_file.write(data) -def generate_argparse(): +def generate_argparse() -> ArgumentParser: """Generate Melpomene's generator input parser""" - parser = argparse.ArgumentParser( - description="Helper that can generate JSON / JS / HTML files for Melpomene webcomic reader" + parser = ArgumentParser( + description=( + "Helper that can generate JSON / JS / " + "HTML files for Melpomene webcomic reader" + ) ) parser.add_argument( @@ -140,7 +163,7 @@ def generate_argparse(): return parser -if __name__ == "__main__": +def run(): args = generate_argparse().parse_args() # Get the final outout name @@ -160,13 +183,17 @@ if __name__ == "__main__": elif args.output_format == "js" and not output.endswith(".js"): output += ".js" - zooms, max_width, max_height = extract_zooms(args.svg_folders) + zooms = extract_zooms(args.svg_folders) if args.output_format == "html": - write_html(zooms, output, max_width, max_height, args.p, args.e) + write_html(zooms, output, args.p, args.e) elif args.output_format == "json": write_json_or_js(zooms, output, False) elif args.output_format == "js": write_json_or_js(zooms, output, True) + + +if __name__ == "__main__": + run() From 25cb2693346d57a6e75fd3af7d2d9735125ac8b2 Mon Sep 17 00:00:00 2001 From: Kronk Date: Sun, 25 Jun 2023 11:13:44 +0200 Subject: [PATCH 21/22] Added VSCode settings to README. Added .vscode to .gitignore. --- .gitignore | 3 +++ README.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/.gitignore b/.gitignore index 0916cb9..2b73a23 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ eslint_report.html # Demo sources demos/src_highres demos/src_lowres + +# Local dev environment settings +.vscode \ No newline at end of file diff --git a/README.md b/README.md index 16a3653..aa5757d 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,38 @@ To setup prospector, you need to run: + `prospector -s veryhigh -w mypy --max-line-length 88 .` + `black .` +For VSCode users, you can run those automatically in your IDE. Here is what your .vscode/settings.json file should include : + ```json + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/*.pyc": true, + "**/__pycache__": true + }, + // Replace by your own venv python path + "python.defaultInterpreterPath": "~\\.virtualenvs\\melpomene-ajDJjHHp\\Scripts\\python.exe", + "python.formatting.provider": "black", + "[python]": { + "editor.formatOnType": true, + }, + "python.linting.enabled": true, + "python.linting.prospectorEnabled": true, + "python.linting.prospectorArgs": [ + "-s", + "veryhigh", + "-w", + "mypy", + "--max-line-length", + "88" + ], + "editor.rulers": [ + 88 + ] + ``` # Credits Most examples and the documentation of Melpomene uses illustrations from David "Deevad" Revoy's "Pepper & Carrot" webcomic, which is published under CC-BY 4.0. Full licence [here](https://www.peppercarrot.com/en/license/index.html).  From 757ff3a7c7e77d6a9bd81a1fbebbdd034c13eb04 Mon Sep 17 00:00:00 2001 From: Kronk Date: Sun, 25 Jun 2023 11:24:14 +0200 Subject: [PATCH 22/22] Fixed vscode settings markdown. --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aa5757d..7b7ad46 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,9 @@ To setup prospector, you need to run: + `prospector -s veryhigh -w mypy --max-line-length 88 .` + `black .` -For VSCode users, you can run those automatically in your IDE. Here is what your .vscode/settings.json file should include : - ```json +For VSCode users, you can run those automatically in your IDE. Here is what your .vscode/settings.json file should include : + +```json "files.exclude": { "**/.git": true, "**/.svn": true, @@ -157,8 +158,8 @@ For VSCode users, you can run those automatically in your IDE. Here is what your ], "editor.rulers": [ 88 - ] - ``` + ], +``` # Credits Most examples and the documentation of Melpomene uses illustrations from David "Deevad" Revoy's "Pepper & Carrot" webcomic, which is published under CC-BY 4.0. Full licence [here](https://www.peppercarrot.com/en/license/index.html).