TagoDR / MangaOnlineViewer

This scripts loads all pages(images) from the current chapter of the manga showing them in one page in a list type structure, witch helps reading faster.
381 stars 46 forks source link
javascript manga nodejs reader tampermonkey userscript viewer

Manga OnlineViewer

Manga Icon Adult Script Manga Icon Main Script Manga Icon Dev Script

Description

Loads all pages from a chapter in a nice view, allowing for faster and more comfortable reading, without the need to wait for pages to load.

:exclamation: Attention: Some sites require you to reload the page(F5) or open the chapter in a new tab for the script to start.

Supported Browsers

Firefox and Chrome with Tampermonkey or Violentmonkey. Other Browsers with other add-ons may also work, but not officially supported.

Installation

Main Reader

Adult Reader

Official Source: GitHub

Local Files (ZIP, CBZ, CBR..., PNGs, JPGs...)

Save this file index.html, then open it in the browser, and you will see the options to load local Files.

Supported Manga Sites

Supported Comic Sites

Supported Hentai Sites

Adult Script available only on GitHub

HotKeys

Features

Adding new Manga Sites

Fork this project and make a pull request, in the folders "main" or "adult" create a new file .ts with The name of the site. After writing the module like below, import it from the index of the selected folder

Inside the file, gather the information needed using any means, look at other sites for inspiration, Below is an example with descriptions.

// == MangaDex =====================================================================================
export default {
    name: 'MangaDex', // The name of the to be listed, may be an array of names
    url: /https?:\/\/(www\.)?mangadex.org/, // Regex to detect the site, usually just the reader part of the site, but can be the root if is has a lot of dynamic content
    homepage: 'https://mangadex.org/',   // Link for the home page of the site, may be an array of urls
    language: ['English'], // Array of languages the site serve
    category: 'manga', // Category of the site
    waitEle: '#chapter-selector a', // Wait for something before running, some site requires some steps before the information is available
    async run() {
        // Logic for obtaining the required information
        const chapterId = /\/chapter\/([^/]+)(\/\d+)?/.exec(window.location.pathname)?.at(1);
        const home = `https://api.mangadex.org/at-home/server/${chapterId}`;
        const server = await fetch(home).then(async (res) => res.json());
        const images = server.chapter.data;
        const chapters = document.querySelectorAll('#chapter-selector a');
        return {
            title: document.querySelector('title')?.text.replace(' - MangaDex', ''), // Title of the Chapter/Manga
            series: document.querySelector("a.text-primary[href^='/title/']")?.getAttribute('href'), // Url for the gallery or chapter list
            pages: images.length, // Quantity of pages
            prev: chapters?.item(0)?.getAttribute('href'), // Previous Chapter
            next: chapters?.item(1)?.getAttribute('href'), // Next Chapter
            listImages: images.map(  // List of images
                    (img: string) => `${server.baseUrl}/data/${server.chapter.hash}/${img}`,
            ),
        };
    },
};

Look inside the types folder to better understand the structure and valid values.

Permissions

I allow this script to be posted or used anywhere as long as I am given credit and provided a link to this site. I allow parts of my script to be used freely.

Disclaimer

In case the owner/admin of one of the supported sites does not want my script to run on their site, I will make it disabled by default. Forcing users to manually activate it.

Mobile

It's recommended to use Tampermonkey with Firefox mobile or Kiwi Browser.

Bookmarklet (Not Recommended)

Settings can't be saved with Bookmarklet:

Bookmarklet seems to work only in Chrome, open the chapter then use the search bar to activate your bookmarklet.

Main Reader:
javascript:(function() {
    if (unsafeWindow === undefined) unsafeWindow = window;
    ["https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.6.0/tinycolor.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/5.0.0/imagesloaded.pkgd.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jszip/3.9.1/jszip.min.js", "https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js", "https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/11.4.8/sweetalert2.min.js", "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js", "https://cdn.jsdelivr.net/npm/hotkeys-js@3.13.7/dist/hotkeys.min.js", "https://cdn.jsdelivr.net/npm/range-slider-input@2.4.4/dist/rangeslider.nostyle.umd.min.js", "https://cdnjs.cloudflare.com/ajax/libs/UAParser.js/1.0.37/ua-parser.min.js", "https://cdnjs.cloudflare.com/ajax/libs/blob-util/2.0.2/blob-util.min.js", "https://cdn.jsdelivr.net/gh/TagoDR/MangaOnlineViewer@latest/dist/Manga_OnlineViewer.user.min.js"].map(s => document.body.appendChild(document.createElement('script')).src = s)
})();
Adult Reader:
javascript:(function() {
    if (unsafeWindow === undefined) unsafeWindow = window;
    ["https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.6.0/tinycolor.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/5.0.0/imagesloaded.pkgd.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jszip/3.9.1/jszip.min.js", "https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.js", "https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/11.4.8/sweetalert2.min.js", "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js", "https://cdn.jsdelivr.net/npm/hotkeys-js@3.13.7/dist/hotkeys.min.js", "https://cdn.jsdelivr.net/npm/range-slider-input@2.4.4/dist/rangeslider.nostyle.umd.min.js", "https://cdnjs.cloudflare.com/ajax/libs/UAParser.js/1.0.37/ua-parser.min.js", "https://cdnjs.cloudflare.com/ajax/libs/blob-util/2.0.2/blob-util.min.js", "https://cdn.jsdelivr.net/gh/TagoDR/MangaOnlineViewer@latest/dist/Manga_OnlineViewer_Adult.user.min.js"].map(s => document.body.appendChild(document.createElement('script')).src = s)
})();