### Print Version (CLI) Source: https://context7.com/kha-white/mokuro/llms.txt Display the installed mokuro version and exit. ```bash mokuro --version ``` -------------------------------- ### Install Mokuro Source: https://github.com/kha-white/mokuro/blob/master/README.md Install the mokuro package using pip. Ensure Python 3.10 or newer is installed. Check PyTorch website for Python version compatibility. ```bash pip3 install mokuro ``` -------------------------------- ### Install Mokuro Source: https://context7.com/kha-white/mokuro/llms.txt Install the mokuro package using pip. ```bash pip install mokuro ``` -------------------------------- ### Install Mokuro Source: https://github.com/kha-white/mokuro/blob/master/notebooks/mokuro_demo.ipynb Installs the mokuro package using pip. Run this cell first to ensure the tool is available. ```python !pip install mokuro ``` -------------------------------- ### Mokuro CLI Usage Source: https://context7.com/kha-white/mokuro/llms.txt Examples of how to use the mokuro command-line interface for various processing tasks. ```APIDOC ## CLI: `mokuro` entry point The main command-line interface, powered by [python-fire](https://github.com/google/python-fire). Accepts one or more volume paths or a parent directory, plus many optional flags. ```bash # Install pip install mokuro # Process a single volume (directory of manga images) mokuro /path/to/manga/vol1 # Process multiple volumes at once mokuro /path/to/manga/vol1 /path/to/manga/vol2 /path/to/manga/vol3 # Process all volumes inside a parent directory # Expected structure: manga_title/vol1/, manga_title/vol2/, ... mokuro --parent_dir /path/to/manga_title/ # Process a zip/cbz archive and unzip it in place mokuro --unzip /path/to/manga/vol1.cbz # Skip OCR (generate .mokuro structure files only, no text) mokuro --disable_ocr /path/to/manga/vol1 # Use a custom manga-ocr model (local path or HuggingFace model ID) mokuro --pretrained_model_name_or_path /models/my-ocr-model /path/to/manga/vol1 # Force CPU inference even if CUDA is available mokuro --force_cpu /path/to/manga/vol1 # Suppress the interactive confirmation prompt mokuro --disable_confirmation /path/to/manga/vol1 # Continue processing remaining volumes even if one fails mokuro --ignore_errors --parent_dir /path/to/manga_title/ # Re-process pages ignoring any cached _ocr results mokuro --no_cache /path/to/manga/vol1 # Disable legacy HTML output (only .mokuro files are produced) mokuro --disable_html /path/to/manga/vol1 # Print the installed version and exit mokuro --version # Output: 0.2.4 ``` ``` -------------------------------- ### Trigger Pan Start Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Initiates the pan start event and begins smooth scrolling. It ensures the 'panstart' event is only triggered once. ```javascript function triggerPanStart(){if(!panstartFired){triggerEvent("panstart");panstartFired=true;smoothScroll.start()}} ``` -------------------------------- ### Make DOM Controller Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Creates a controller for interacting with a DOM element for panzoom functionality. Ensures the element is attached to the DOM and provides methods for getting bounding box and applying transformations. ```javascript function makeDomController(domElement,options){var elementValid=isDomElement(domElement);if(!elementValid){throw new Error("panzoom requires DOM element to be attached to the DOM tree")} var owner=domElement.parentElement;domElement.scrollTop=0;if(!options.disableKeyboardInteraction){owner.setAttribute("tabindex",0)} var api={getBBox:getBBox,getOwner:getOwner,applyTransform:applyTransform};return api;function getOwner(){return owner}function getBBox(){return{left:0,top:0,width:domElement.clientWidth,height:domElement.clientHeight}}function applyTransform(transform){domElement.style.transformOrigin="0 0 0";domElement.style.transform="matrix("+transform.scale+", 0, 0, "+transform.scale+", "+transform.x+", "+transform.y+")"}}function isDomElement(element){return element&&element.parentElement&&element.style}} ``` -------------------------------- ### Resolve .mokuro Path Source: https://context7.com/kha-white/mokuro/llms.txt Get the canonical .mokuro path for any given volume path, regardless of its original archive format. ```python print(get_path_mokuro(Path("/manga/series1/vol1"))) # /manga/series1/vol1.mokuro print(get_path_mokuro(Path("/manga/series1/vol1.cbz"))) # /manga/series1/vol1.mokuro ``` -------------------------------- ### Start Touch Listener Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Ensures that touch move and end event listeners are attached to the document only when a touch interaction is in progress. This prevents unnecessary event listener overhead. ```javascript function startTouchListenerIfNeeded(){if(touchInProgress){return}touchInProgress=true;document.addEventListener("touchmove",handleTouchMove);document.addEventListener("touchend",handleTouchEnd);document.addEventListener("touchcancel",handleTouchEnd)} ``` -------------------------------- ### List OCR JSON Paths Source: https://context7.com/kha-white/mokuro/llms.txt Get a dictionary of paths to cached OCR JSON files for each page within a volume, keyed by page identifier. ```python # List cached OCR JSON paths json_paths = vol.get_json_paths() # {"000a": PosixPath("000a.json"), ...} ``` -------------------------------- ### Make SVG Controller Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Creates a controller for interacting with an SVG element for panzoom functionality. It ensures the SVG element is valid and provides methods for getting bounding box, screen transformation matrix, and applying transformations. ```javascript function makeSvgController(svgElement,options){if(!isSVGElement(svgElement)){throw new Error("svg element is required for svg.panzoom to work")}var owner=svgElement.ownerSVGElement;if(!owner){throw new Error("Do not apply panzoom to the root element. "+"Use its child instead (e.g. ). "+"As of March 2016 only FireFox supported transform on the root element")}if(!options.disableKeyboardInteraction){owner.setAttribute("tabindex",0)}var api={getBBox:getBBox,getScreenCTM:getScreenCTM,getOwner:getOwner,applyTransfor ``` -------------------------------- ### Make DOM Controller Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html Creates a controller for interacting with a DOM element, providing methods to get its bounding box, owner element, and apply transformations. It validates that the element is attached to the DOM. ```javascript module.exports=makeDomController;module.exports.canAttach=isDomElement;function makeDomController(domElement,options){var elementValid=isDomElement(domElement);if(!elementValid){throw new Error("panzoom requires DOM element to be attached to the DOM tree")}var owner=domElement.parentElement;domElement.scrollTop=0;if(!options.disableKeyboardInteraction){owner.setAttribute("tabindex",0)}var api={getBBox:getBBox,getOwner:getOwner,applyTransform:applyTransform};return api;function getOwner(){return owner}function getBBox(){return{left:0,top:0,width:domElement.clientWidth,height:domElement.clientHeight}}function applyTransform(transform){domElement.style.transformOrigin="0 0 0";domElement.style.transform="matrix("+transform.scale+", 0, 0, "+transform.scale+", "+transform.x+", "+transform.y+")"}}function isDomElement(element){return element&&element.parentElement&&element.style} ``` -------------------------------- ### Handle Mouse Down Event Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Initiates mouse interaction by capturing the starting position and setting up event listeners for mouse movement and release. It prevents default behavior for non-left clicks and ongoing touches. ```javascript function onMouseDown(e){if(beforeMouseDown(e))return;if(touchInProgress){e.stopPropagation();return false}var isLeftButton=e.button===1&&window.event!==null||e.button===0;if(!isLeftButton)return;smoothScroll.cancel();var offset=getOffsetXY(e);var point=transformToScreen(offset.x,offset.y);mouseX=point.x;mouseY=point.y;document.addEventListener("mousemove",onMouseMove);document.addEventListener("mouseup",onMouseUp);textSelection.capture(e.target||e.srcElement);return false} ``` -------------------------------- ### Initialize Application on DOM Load Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Sets up the application when the DOM is fully loaded. This includes loading state, initializing panzoom, and setting up event listeners. ```javascript document.addEventListener('DOMContentLoaded', function () { loadState(); num_pages = document.getElementsByClassName("page").length; checkImagesAndAlert(); pz = panzoom(pc, { bounds: true, boundsPadding: 0.05, maxZoom: 10, minZoom: 0.1, zoomDoubleClickSpeed: 1, enableTextSelection: true, beforeMouseDown: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target) || (e.target.closest('.textBox') !== null) || (state.ctrlToPan && !e.ctrlKey); return shouldIgnore; }, beforeWheel: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target); return shouldIgnore; }, onTouch: function (e) { if (disablePanzoomOnElement(e.target)) { e.stopPropagation(); return false; } if (e.touches.length > 1) { return true; } else { return false; } } }); updatePage(state.page_idx); initTextBoxes(); if (showAboutOnStart) { document.getElementById('popupAbout').style.display = 'block'; document.getElementById('dimOverlay').style.display = 'initial'; pz.pause(); } }, false); ``` -------------------------------- ### Initialize Volume Management Classes Source: https://context7.com/kha-white/mokuro/llms.txt Import and initialize VolumeCollection and Volume for scanning and deduplicating input paths into Volume objects, grouping them under their parent Title. ```python from pathlib import Path from mokuro.volume import VolumeCollection, Volume, get_path_mokuro ``` -------------------------------- ### Run Mokuro CLI Source: https://github.com/kha-white/mokuro/blob/master/notebooks/mokuro_demo.ipynb Executes the Mokuro command-line tool. Specify the parent directory containing your manga using the --parent_dir flag. Ensure Google Drive is mounted if using a path within it. ```bash !mokuro --parent_dir "/content/drive/MyDrive/manga/UchiNoNyan'sDiary" ``` -------------------------------- ### Get Current Pan Position Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Returns the current pan position as an object with x and y coordinates. ```javascript function getPoint(){return{x:transform.x,y:transform.y}} ``` -------------------------------- ### Rigid Scroll Implementation Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Returns an object with no-operation functions for start, stop, and cancel, representing a non-scrolling behavior. ```javascript function rigidScroll(){return{start:noop,stop:noop,cancel:noop}} ``` -------------------------------- ### Get Offset XY from Event Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Calculates the mouse or touch coordinates relative to the owner element's bounding box. ```javascript function getOffsetXY(e){var offsetX,offsetY;var ownerRect=owner.getBoundingClientRect();offsetX=e.clientX-ownerRect.left;offsetY=e.clientY-ownerRect.top;return{x:offsetX,y:offsetY}} ``` -------------------------------- ### Initialize Panzoom and Event Listeners Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr_disable_ocr/vol1.html Sets up the panzoom library for interactive zooming and panning, and attaches event listeners for various UI interactions upon DOMContentLoaded. Includes custom logic for disabling panzoom on specific elements. ```javascript document.addEventListener('DOMContentLoaded', function () { loadState(); num_pages = document.getElementsByClassName("page").length; checkImagesAndAlert(); pz = panzoom(pc, { bounds: true, boundsPadding: 0.05, maxZoom: 10, minZoom: 0.1, zoomDoubleClickSpeed: 1, enableTextSelection: true, beforeMouseDown: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target) || (e.target.closest('.textBox') !== null) || (state.ctrlToPan && !e.ctrlKey); return shouldIgnore; }, beforeWheel: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target); return shouldIgnore; }, onTouch: function (e) { if (disablePanzoomOnElement(e.target)) { e.stopPropagation(); return false; } if (e.touches.length > 1) { return true; } else { return false; } } }); updatePage(state.page_idx); initTextBoxes(); if (showAboutOnStart) { document.getElementById('popupAbout').style.display = 'block'; document.getElementById('dimOverlay').style.display = 'initial'; pz.pause(); } }, false); ``` -------------------------------- ### Initialize Panzoom and Event Listeners Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Sets up panzoom for the main content area and initializes various event listeners for UI controls. It also handles initial state loading and display of an about popup if configured. ```javascript document.addEventListener('DOMContentLoaded', function () { loadState(); num_pages = document.getElementsByClassName("page").length; checkImagesAndAlert(); pz = panzoom(pc, { bounds: true, boundsPadding: 0.05, maxZoom: 10, minZoom: 0.1, zoomDoubleClickSpeed: 1, enableTextSelection: true, beforeMouseDown: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target) || (e.target.closest('.textBox') !== null) || (state.ctrlToPan && !e.ctrlKey); return shouldIgnore; }, beforeWheel: function (e) { let shouldIgnore = disablePanzoomOnElement(e.target); return shouldIgnore; }, onTouch: function (e) { if (disablePanzoomOnElement(e.target)) { e.stopPropagation(); return false; } if (e.touches.length > 1) { return true; } else { return false; } } }); updatePage(state.page_idx); initTextBoxes(); if (showAboutOnStart) { document.getElementById('popupAbout').style.display = 'block'; document.getElementById('dimOverlay').style.display = 'initial'; pz.pause(); } }, false); ``` -------------------------------- ### Build Volume Collection from Paths Source: https://context7.com/kha-white/mokuro/llms.txt Create a VolumeCollection by adding paths to individual volumes or zip/cbz archives. The collection automatically deduplicates identical volumes. ```python vc = VolumeCollection() vc.add_path_in(Path("/manga/series1/vol1")) vc.add_path_in(Path("/manga/series1/vol2.zip")) vc.add_path_in(Path("/manga/series1/vol2")) # same volume, different format print(len(vc)) # 2 (vol1 and vol2 deduplicated) for volume in vc: # iterates in natural sort order print(volume) # /manga/series1/vol1 (unprocessed) # /manga/series1/vol2.zip (already processed) ``` -------------------------------- ### Get and Set Zoom Speed Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Retrieves or sets the speed at which zooming occurs. Throws an error if the new speed is not a finite number. ```javascript function getZoomSpeed(){return speed};function setZoomSpeed(newSpeed){if(!Number.isFinite(newSpeed)){throw new Error("Zoom speed should be a number")};speed=newSpeed} ``` -------------------------------- ### Mokuro Python API (`run` function) Source: https://context7.com/kha-white/mokuro/llms.txt Programmatic usage of the mokuro functionality through the `run` function, mirroring CLI options. ```APIDOC ## `run()` — Python API entry point `mokuro.run.run()` exposes the same functionality as the CLI for programmatic use. All parameters mirror the CLI flags. ```python from mokuro.run import run # Process a single volume, skip confirmation prompt, force CPU run( "/path/to/manga/vol1", disable_confirmation=True, force_cpu=True, ) # Process multiple volumes, skip OCR, don't produce HTML run( "/path/to/manga/vol1", "/path/to/manga/vol2", disable_confirmation=True, disable_ocr=True, legacy_html=False, ) # Process all volumes under a parent directory with error resilience run( parent_dir="/path/to/manga_title/", disable_confirmation=True, ignore_errors=True, no_cache=True, ) # Use a locally downloaded manga-ocr model run( "/path/to/manga/vol1", pretrained_model_name_or_path="/models/manga-ocr-base", disable_confirmation=True, ) ``` **Parameters:** | Parameter | Type | Default | Description | |---|---|---|---| | `*paths` | `str | Path` | — | Volume paths (directories, `.zip`, `.cbz`) | | `parent_dir` | `str | Path | None` | `None` | Scan all volumes inside this directory | | `pretrained_model_name_or_path` | `str` | `"kha-white/manga-ocr-base"` | HuggingFace model ID or local path | | `force_cpu` | `bool` | `False` | Disable CUDA even if available | | `disable_confirmation` | `bool` | `False` | Skip the interactive "Continue? [yes/no]" prompt | | `disable_ocr` | `bool` | `False` | Generate output files without OCR text | | `ignore_errors` | `bool` | `False` | Skip failed pages/volumes instead of raising | | `no_cache` | `bool` | `False` | Ignore cached `_ocr/` results and re-run OCR | | `unzip` | `bool` | `False` | Extract zip/cbz archives to their original location | | `legacy_html` | `bool` | `True` | Also produce a legacy `.html` file per volume | | `as_one_file` | `bool` | `True` | Embed CSS/JS in HTML (legacy mode only) | | `version` | `bool` | `False` | Print version and return | ``` -------------------------------- ### Animation Frame Utilities Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr_disable_ocr/vol1.html Provides functions to get the correct `requestAnimationFrame` and `cancelAnimationFrame` based on the browser environment. Includes fallbacks to `setTimeout` and `clearTimeout`. ```javascript function getCancelAnimationFrame(){if(typeof cancelAnimationFrame==="function")return cancelAnimationFrame; return clearTimeout} function getRequestAnimationFrame(){if(typeof requestAnimationFrame==="function")return requestAnimationFrame; return function(handler){return setTimeout(handler,16)}} ``` -------------------------------- ### Initialize Panzoom Script Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html This script initializes the panzoom library by finding the script tag, collecting attributes as options, and attaching the panzoom functionality to a specified DOM element. It includes error handling for missing elements and a retry mechanism. ```javascript yTagName("script");if(!scripts)return;var panzoomScript;for(var i=0;i 1) { return true; } else { return false; } } }); updatePage(state.page_idx); initTextBoxes(); if (showAboutOnStart) { document.getElementById('popupAbout').style.display = 'block'; document.getElementById('dimOverlay').style.display = 'initial'; pz.pause(); } }, false); function disablePanzoomOnElement(element) { return document.getElementById('topMenu').contains(element); } ``` -------------------------------- ### Run Mokuro on Multiple Volumes Source: https://github.com/kha-white/mokuro/blob/master/README.md Process multiple manga volumes sequentially. A separate HTML file will be generated for each volume. ```bash mokuro /path/to/manga/vol1 /path/to/manga/vol2 /path/to/manga/vol3 ``` -------------------------------- ### Get Scale Multiplier from Delta Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Calculates the scale multiplier for zooming based on the mouse wheel scroll delta. Adjusts speed based on a configurable factor. ```javascript function getScaleMultiplier(delta){var sign=Math.sign(delta);var deltaAdjustedSpeed=Math.min(.25,Math.abs(speed*delta/128));return 1-sign*deltaAdjustedSpeed} ``` -------------------------------- ### Mokuro State Management Initialization Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html Initializes the state for the Mokuro application, including default values for page index, view modes, and display settings. Persists state using localStorage. ```javascript let num_pages = -1; let pc = document.getElementById('pagesContainer'); let r = document.querySelector(':root'); let pz; let showAboutOnStart = false; let storageKey = "mokuro_" + window.location.pathname; let defaultState = { page_idx: 0, page2_idx: -1, hasCover: false, r2l: true, singlePageView: false, ctrlToPan: false, textBoxBorders: false, editableText: false, displayOCR: true, fontSize: "auto", eInkMode: false, defaultZoomMode: "fit to screen", toggleOCRTextBoxes: false, backgroundColor: '#C4C3D0', }; let state = JSON.parse(JSON.stringify(defaultState)); function saveState() { localStorage.setItem(storageK ``` -------------------------------- ### Get Transform Origin Offset Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Calculates the offset coordinates based on the transform origin. This is used to center zoom or pan operations around a specific point. ```javascript function getTransformOriginOffset(){var ownerRect=owner.getBoundingClientRect();return{x:ownerRect.width*transformOrigin.x,y:ownerRect.height*transformOrigin.y}} ``` -------------------------------- ### Get and Set Zoom Limits Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Retrieves or sets the minimum and maximum zoom levels allowed for the pan controller. Ensures zoom levels are finite numbers. ```javascript function getMinZoom(){return minZoom};function setMinZoom(newMinZoom){minZoom=newMinZoom};function getMaxZoom(){return maxZoom};function setMaxZoom(newMaxZoom){maxZoom=newMaxZoom} ``` -------------------------------- ### Process a Single Manga Volume (CLI) Source: https://context7.com/kha-white/mokuro/llms.txt Process a single directory containing manga images. This command initiates the OCR and metadata generation process. ```bash mokuro /path/to/manga/vol1 ``` -------------------------------- ### Handle Mouse Down for Panning Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Initiates panning when the left mouse button is pressed. It captures the starting mouse coordinates and prevents interaction if touch events are already in progress. ```javascript function onMouseDown(e){if(beforeMouseDown(e))return;if(touchInProgress){e.stopPropagation();return false}var isLeftButton=e.button===1&&window.event!==null||e.button===0;if(!isLeftButton)return;smoothScroll.cancel();var offset=getOffsetXY(e);var point=transformToScreen(offset.x,offset.y);mouseX=point.x;mouseY=point.y;document. ``` -------------------------------- ### MokuroGenerator Source: https://context7.com/kha-white/mokuro/llms.txt Orchestrates OCR across all pages in a volume and writes the .mokuro JSON file. It lazily initializes the underlying ML models on first use. ```APIDOC ## `MokuroGenerator` — Volume processing class `mokuro.mokuro_generator.MokuroGenerator` orchestrates OCR across all pages in a volume and writes the `.mokuro` JSON file. It lazily initializes the underlying ML models on first use. ```python from pathlib import Path from mokuro.mokuro_generator import MokuroGenerator from mokuro.volume import Volume # Create a generator (models are not loaded until process_volume() is first called) mg = MokuroGenerator( pretrained_model_name_or_path="kha-white/manga-ocr-base", force_cpu=False, disable_ocr=False, ) # Construct a Volume object pointing to a directory of manga images vol = Volume(Path("/path/to/manga/vol1")) vol.title = ... # set by VolumeCollection in normal workflow # Run OCR on every page; results cached to /path/to/manga/_ocr/vol1/*.json mg.process_volume(vol, ignore_errors=False, no_cache=False) # Output: /path/to/manga/vol1.mokuro # Generate (or regenerate) just the .mokuro file from existing _ocr cache MokuroGenerator.generate_mokuro_file(vol, ignore_errors=False) ``` ### `.mokuro` output file format ```json { "version": "0.2.4", "title": "manga_title", "title_uuid": "73af593b-eb0a-4c0e-9ae9-70e76a607da0", "volume": "vol1", "volume_uuid": "1f55a3b0-34f5-4415-ac85-8d906a71adcd", "pages": [ { "version": "0.2.4", "img_width": 827, "img_height": 1170, "img_path": "000a.jpg", "blocks": [ { "box": [37, 0, 863, 235], "vertical": false, "font_size": 137.5, "lines_coords": [ [[582.0, 18.0], [785.0, 13.0], [787.0, 53.0], [583.0, 58.0]] ], "lines": ["ダイアリー・"] } ] } ] } ``` ``` -------------------------------- ### Smooth Zoom to Absolute Scale Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr/vol1.html Animates the zoom level to a specific absolute scale value. It cancels any ongoing scroll or zoom animations before starting the new one. ```javascript function smoothZoomAbs(clientX,clientY,toScaleValue){var fromValue=transform.scale;var from={scale:fromValue};var to={scale:toScaleValue};smoothScroll.cancel();cancelZoomAnimation();zoomToAnimation=animate(from,to,{step:function(v){zoomAbs(clientX,clientY,v.scale)}})} ``` -------------------------------- ### Process All Volumes in a Parent Directory (CLI) Source: https://context7.com/kha-white/mokuro/llms.txt Process all manga volumes found within a specified parent directory. Assumes a standard directory structure for volumes. ```bash mokuro --parent_dir /path/to/manga_title/ ``` -------------------------------- ### Get Center Point of Owner Element Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Calculates and returns the midpoint coordinates of the owner element's bounding rectangle. This is often used as a reference point for transformations. ```javascript function midPoint(){var ownerRect=owner.getBoundingClientRect();return{x:ownerRect.width/2,y:ownerRect.height/2}} ``` -------------------------------- ### Get Scene Bounding Box Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Retrieves the bounding box of the scene. If bounds are boolean, it calculates dimensions based on padding; otherwise, it returns the defined bounds object. ```javascript function getBoundingBox(){if(!bounds)return;if(typeof bounds==="boolean"){var ownerRect=owner.getBoundingClientRect();var sceneWidth=ownerRect.width;var sceneHeight=ownerRect.height;return{left:sceneWidth*boundsPadding,top:sceneHeight*boundsPadding,right:sceneWidth*(1-boundsPadding),bottom:sceneHeight*(1-boundsPadding)}};return bounds} ``` -------------------------------- ### Process a Zip/CBZ Archive (CLI) Source: https://context7.com/kha-white/mokuro/llms.txt Process a manga archive file (.zip or .cbz). The archive will be extracted in place before processing. ```bash mokuro --unzip /path/to/manga/vol1.cbz ``` -------------------------------- ### Initialize Text Box Event Listeners Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html Sets up event listeners for text boxes to handle hover states and toggling OCR text boxes based on application state. Also manages clicks outside text boxes to remove hover states. ```javascript function initTextBoxes() { // Add event listeners for toggling ocr text boxes with the toggleOCRTextBoxes option. let textBoxes = document.querySelectorAll('.textBox'); for (let i = 0; i < textBoxes.length; i++) { textBoxes[i].addEventListener('click', function (e) { if (state.toggleOCRTextBoxes) { this.classList.add('hovered'); // Remove hovered state from all other .textBoxes for (let j = 0; j < textBoxes.length; j++) { if (i !== j) { textBoxes[j].classList.remove('hovered'); } } } }); } // When clicking off of a .textBox, remove the hovered state. document.addEventListener('click', function (e) { if (state.toggleOCRTextBoxes) { if (e.target.closest('.textBox') === null) { let textBoxes = document.querySelectorAll('.textBox'); for (let i = 0; i < textBoxes.length; i++) { textBoxes[i].classList.remove('hovered'); } } } }); } ``` -------------------------------- ### Access Model Weight Cache Source: https://context7.com/kha-white/mokuro/llms.txt Utilize the `mokuro.cache.cache` singleton to access the path to the `comictextdetector.pt` model weight file. The cache automatically downloads the file if it's not present. ```python from mokuro.cache import cache # Access the path to the detector weights, downloading if not present model_path = cache.comic_text_detector # Downloads from: # https://github.com/zyddnys/manga-image-translator/releases/download/beta-0.2.1/comictextdetector.pt # Saved to: ~/.cache/manga-ocr/comictextdetector.pt print(model_path) # PosixPath('/home/user/.cache/manga-ocr/comictextdetector.pt') # Custom cache location via environment variable import os os.environ["XDG_CACHE_HOME"] = "/data/caches" # cache root will be /data/caches/manga-ocr/ ``` -------------------------------- ### Bezier Easing Functions Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr_disable_ocr/vol1.html Provides common Bezier easing functions for animations, including ease, easeIn, easeOut, and easeInOut. ```javascript var BezierEasing=require("bezier-easing"); var animations={ ease:BezierEasing(.25,.1,.25,1), easeIn:BezierEasing(.42,0,1,1), easeOut:BezierEasing(0,0,.58,1), easeInOut:BezierEasing(.42,0,.58,1), linear:BezierEasing(0,0,1,1) }; module.exports=animate; module.exports.makeAggregateRaf=makeAggregateRaf; module.exports.sharedScheduler=makeAggregateRaf() ``` -------------------------------- ### Initialize and Manage OCR Text Box Interactions Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr_disable_ocr/vol1.html Sets up event listeners for OCR text boxes, allowing them to be highlighted when the 'toggleOCRTextBoxes' option is enabled. Also handles removing the highlight when clicking outside of a text box. ```javascript function initTextBoxes() { // Add event listeners for toggling ocr text boxes with the toggleOCRTextBoxes option. let textBoxes = document.querySelectorAll('.textBox'); for (let i = 0; i < textBoxes.length; i++) { textBoxes[i].addEventListener('click', function (e) { if (state.toggleOCRTextBoxes) { this.classList.add('hovered'); // Remove hovered state from all other .textBoxes for (let j = 0; j < textBoxes.length; j++) { if (i !== j) { textBoxes[j].classList.remove('hovered'); } } } }); } // When clicking off of a .textBox, remove the hovered state. document.addEventListener('click', function (e) { if (state.toggleOCRTextBoxes) { if (e.target.closest('.textBox') === null) { let textBoxes = document.querySelectorAll('.textBox'); for (let i = 0; i < textBoxes.length; i++) { textBoxes[i].classList.remove('hovered'); } } } }); } ``` -------------------------------- ### Page View Logic Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html Determines if the current page is the first of a pair based on view settings (single page vs. double page) and whether the document has a cover page. Also provides functions to get page elements and offsets. ```javascript function isPageFirstOfPair(page_idx) { if (state.singlePageView) { return true; } else { if (state.hasCover) { return (page_idx === 0 || (page_idx % 2 === 1)); } else { return page_idx % 2 === 0; } } } ``` ```javascript function getPage(page_idx) { return document.getElementById("page" + page_idx); } ``` ```javascript function getOffsetLeft() { return 0; } ``` ```javascript function getOffsetTop() { let offset = 0; let menu = document.getElementById('topMenu'); if (!menu.classList.contains("hidden")) { offset += menu.getBoundingClientRect().bottom + 10; } return offset; } ``` ```javascript function getOffsetRight() { return 0; } ``` ```javascript function getOffsetBottom() { return 0; } ``` ```javascript function getScreenWidth() { return window.innerWidth - getOffsetLeft() - getOffsetRight(); } ``` ```javascript function getScreenHeight() { return window.innerHeight - getOffsetTop() - getOffsetBottom(); } ``` -------------------------------- ### Use Custom OCR Model (CLI) Source: https://context7.com/kha-white/mokuro/llms.txt Specify a custom manga-ocr model for text recognition. This can be a local path or a HuggingFace model ID. ```bash mokuro --pretrained_model_name_or_path /models/my-ocr-model /path/to/manga/vol1 ``` -------------------------------- ### About Popup and Reset Functionality Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test3_convert_legacy_ocr_disable_ocr/vol1.html Handles the display of an 'About' popup and the reset functionality for the application state. The 'About' popup is shown on click, and the reset function restores the state to its default values. ```javascript document.getElementById('menuAbout').addEventListener('click', function () { document.getElementById('popupAbout').style.display = 'block'; document.getElementById('dimOverlay').style.display = 'initial'; pz.pause(); }, false); ``` ```javascript document.getElementById('menuReset').addEventListener('click', function () { let page_idx = state.page_idx; state = JSON.parse(JSON.stringify(defaultState)); updateUI(); updatePage(page_idx); updateProperties(); }, false); ``` ```javascript document.getElementById('dimOverlay').addEventListener('click', function () { document.getElementById('popupAbout').style.display = 'none'; document.getElementById('dimOverlay').style.display = 'none'; pz.resume(); }, false); ``` -------------------------------- ### Check All Page Images and Alert Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0_disable_ocr/vol1.html Iterates through all pages, extracts background image paths, checks their loading status using `checkImages`, and alerts the user if any images are missing. ```javascript function checkImagesAndAlert() { let imagePaths = []; for (var i = 0; i < num_pages; i++) { let page = getPage(i); let pc = page.getElementsByClassName("pageContainer")[0]; let bg = pc.style.backgroundImage; imagePaths.push(bg.substring(5, bg.length - 2)); } checkImages(imagePaths).then(results => { let missingImages = results.filter(result => !result.status).map(result => result.path); if (missingImages.length > 0) { alert('Some images are missing. Make sure, that images are stored in the folder next to HTML file.\n' + missingImages.join(',\n')); } }); } ``` -------------------------------- ### Run Mokuro on a Directory of Volumes Source: https://github.com/kha-white/mokuro/blob/master/README.md Process all manga volumes within a specified parent directory. This is useful for organizing multiple volumes of a series. ```bash mokuro --parent_dir manga_title/ ``` -------------------------------- ### Image Checking Utilities Source: https://github.com/kha-white/mokuro/blob/master/tests/data/expected_results/test0/vol1.html Provides functions to check if images exist at given paths and to validate all images used in the viewer. It returns promises that resolve with the image path and its status (true if loaded, false if error). ```javascript function checkImage(path) { return new Promise((resolve) => { var img = new Image(); img.onload = function () { resolve({path, status: true}); }; img.onerror = function () { resolve({path, status: false}); }; img.src = path; }); } ``` ```javascript function checkImages(imagePaths) { let promises = imagePaths.map(path => checkImage(path)); return Promise.all(promises); } ``` ```javascript function checkImagesAndAlert() { let imagePaths = []; for (var i = 0; i < num_pages; i++) { let page = getPage(i); let pc = page.getElementsByClassName("pageContainer")[0]; let bg = pc.style.backgroundImage; imagePaths.push(bg.substring(5, bg.length - 2)); } checkImages(imagePaths).then(results => { let missingImages = results.filter(result => !result.status).map(result => result.path); if (missingImages.length > 0) { alert('Some images are missing. Make sure, that images are stored in the folder next to HTML file.\n' + missingImages.join(',\n')); } }); } ``` -------------------------------- ### List Image Paths Source: https://context7.com/kha-white/mokuro/llms.txt Retrieve a dictionary mapping image identifiers to their respective file paths for supported image formats (jpg, jpeg, png, webp) within a volume, sorted naturally. ```python # List image paths (jpg/jpeg/png/webp) in natural sort order img_paths = vol.get_img_paths() # {"000a": PosixPath("000a.jpg"), "000b": PosixPath("000b.jpg"), ...} ```