히토미 뷰어

i,j,k 키를 눌러보세요

Versión del día 11/06/2023. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name           히토미 뷰어
// @name:ko        히토미 뷰어
// @name:en        hitomi viewer
// @description    i,j,k 키를 눌러보세요
// @description:ko i,j,k 키를 눌러보세요
// @description:en press i to open
// @version        2306111344
// @match          https://hitomi.la/*
// @author         nanikit
// @namespace      https://greasyfork.org/ko/users/713014-nanikit
// @connect        self
// @grant          GM_xmlhttpRequest
// @grant          GM_getResourceText
// @grant          GM_openInTab
// @grant          window.close
// @grant          unsafeWindow
// @run-at         document-start
// @require        https://cdn.jsdelivr.net/npm/[email protected]/require.js
// @resource       @stitches/react  https://cdn.jsdelivr.net/npm/@stitches/[email protected]/dist/index.cjs
// @resource       fflate           https://cdn.jsdelivr.net/npm/[email protected]/lib/browser.cjs
// @resource       scheduler        https://cdn.jsdelivr.net/npm/[email protected]/cjs/scheduler.production.min.js
// @resource       object-assign    https://cdn.jsdelivr.net/npm/[email protected]/index.js
// @resource       react            https://cdn.jsdelivr.net/npm/[email protected]/cjs/react.production.min.js
// @resource       react-dom        https://cdn.jsdelivr.net/npm/[email protected]/cjs/react-dom.production.min.js
// @resource       vim_comic_viewer https://greasyfork.org/scripts/417893-vim-comic-viewer/code/vim%20comic%20viewer.js?version=1203635
// ==/UserScript==
// deno-fmt-ignore-file
// deno-lint-ignore-file
'use strict';

if (typeof define !== 'function') {
  throw new Error('requirejs not found.');
}

requirejs.config({
  enforceDefine: true,
});

define('main', (require, exports, module) => {
var timeout = (millisecond) => new Promise((resolve) => setTimeout(resolve, millisecond));
var import_vim_comic_viewer = require("vim_comic_viewer");
var waitDomContent = import_vim_comic_viewer.utils.waitDomContent;
var insertCss = (css) => {
  const style = document.createElement("style");
  style.innerHTML = css;
  document.head.append(style);
};
var domContentLoaded = waitDomContent(window.document);
var observeOnce = (element, options) => {
  return new Promise((resolve) => {
    const observer = new MutationObserver((...args) => {
      observer.disconnect();
      resolve(args);
    });
    observer.observe(element, options);
  });
};
var defaultFocusCss = `
&& {
  background: aliceblue;
}`;
var selectItem = (div) => {
  div.classList.add("key-nav-focus");
  const { left, top, width, height } = div.getBoundingClientRect();
  const centerX = left + width / 2;
  const centerY = top + height / 2;
  const x = centerX - window.innerWidth / 2;
  const y = centerY - window.innerHeight / 2;
  window.scrollBy(x, y);
};
var getFocusedItem = () => document.querySelector(".key-nav-focus") || void 0;
var hookListPage = async (configuration) => {
  const { navigatePage: navigatePage2, getItems: getItems2, enter: enter2, onKeyDown } = configuration;
  const navigateItem = (forward2) => {
    const items = getItems2();
    const focus = getFocusedItem();
    if (!focus) {
      if (items[0]) {
        selectItem(forward2 ? items[0] : items[items.length - 1]);
      }
      return;
    }
    const index = items.indexOf(focus);
    if (index === -1) {
      return;
    }
    focus.classList.remove("key-nav-focus");
    let next = index + (forward2 ? 1 : -1);
    next = Math.max(0, Math.min(next, items.length - 1));
    selectItem(items[next]);
  };
  const forward = (event) => {
    if (onKeyDown) {
      const focus = getFocusedItem();
      onKeyDown(event, focus);
    }
  };
  const handlePageKeypress = (event) => {
    switch (event.key) {
      case "h":
        navigatePage2(-1);
        break;
      case "l":
        navigatePage2(1);
        break;
      default: {
        forward(event);
        break;
      }
    }
  };
  const handleKeyPress = (event) => {
    if (event.target.tagName === "INPUT") {
      return;
    }
    switch (event.key.toLowerCase()) {
      case "j":
        navigateItem(true);
        break;
      case "k":
        navigateItem(false);
        break;
      case "i": {
        const item = getFocusedItem();
        if (item) {
          enter2(item);
        }
        break;
      }
      default:
        if (navigatePage2) {
          handlePageKeypress(event);
        } else {
          forward(event);
        }
        break;
    }
  };
  const insertFocusCss = () => {
    const content = configuration.focusCss || defaultFocusCss;
    insertCss(content.replace(/&/g, ".key-nav-focus"));
  };
  addEventListener("keypress", handleKeyPress);
  await domContentLoaded;
  insertFocusCss();
};
async function hookListPage2() {
  await hookListPage({ enter, getItems, navigatePage });
}
function enter(element) {
  var _a, _b, _c, _d;
  const anchor = (_a = element.querySelector) == null ? void 0 : _a.call(element, "a");
  const fileName = (_d = (_c = (_b = anchor == null ? void 0 : anchor.href) == null ? void 0 : _b.match) == null ? void 0 : _c.call(_b, /\d+\.html/)) == null ? void 0 : _d[0];
  if (fileName) {
    GM_openInTab(`${location.origin}/reader/${fileName}`);
  }
}
function getItems() {
  return [
    ...document.querySelectorAll(".gallery-content > div")
  ];
}
function navigatePage(offset) {
  const link = getOffsetUrl(offset);
  if (link) {
    location.href = link;
  }
}
function getOffsetUrl(offset) {
  const page = getPageList();
  if (!page) {
    return;
  }
  const { index, links } = page;
  return links[index + offset];
}
function getPageList(href) {
  var _a, _b;
  const url = href != null ? href : location.href;
  const lastItem = document.querySelector(".page-container li:last-child");
  if (!(lastItem == null ? void 0 : lastItem.textContent)) {
    return;
  }
  const lastPage = parseInt(lastItem.textContent);
  const currentPage = parseInt((_b = (_a = url.match(/\d+$/)) == null ? void 0 : _a[0]) != null ? _b : "1");
  const anchor = document.querySelectorAll(
    ".page-container li>a[href]"
  )[1];
  if (!anchor) {
    return { links: [url], index: 0 };
  }
  const prefix = anchor.href.replace(/\d+$/, "");
  const links = [];
  for (let i = 1; i <= lastPage; i++) {
    links.push(`${prefix}${i}`);
  }
  return { links, index: currentPage - 1 };
}
var import_vim_comic_viewer2 = require("vim_comic_viewer");
var onReaderKey = (event) => {
  switch (event.key) {
    case "o":
      close();
      break;
  }
};
var waitUnsafeObject = async (name) => {
  while (true) {
    const target = unsafeWindow[name];
    if (target) {
      if (typeof target == "function") {
        return target.bind(unsafeWindow);
      }
      return target;
    }
    await timeout(100);
  }
};
var comicSource = async () => {
  const info = await waitUnsafeObject("galleryinfo");
  prependIdToTitle(info);
  const gg = await waitUnsafeObject("gg");
  const guardless = `${gg.m}`.slice(14, -2).replace(/return 4;/g, "");
  unsafeWindow.gg.m = Function(
    "g",
    guardless
  );
  const make_source_element = await waitUnsafeObject("make_source_element");
  exec(() => {
    const base2 = `${make_source_element}`.match(
      /url_from_url_from_hash\(.*?'(.*?)'\)/
    )[1];
    Object.assign(window, { base: base2 });
  });
  const base = unsafeWindow.base;
  const urlFromUrlFromHash = await waitUnsafeObject(
    "url_from_url_from_hash"
  );
  const urls = info.files.map(
    (file) => urlFromUrlFromHash(
      info.id,
      file,
      file.hasavif ? "avif" : file.haswebp ? "webp" : "jpg",
      void 0,
      base
    )
  );
  return urls;
};
var prependIdToTitle = async (info) => {
  const title = document.querySelector("title");
  for (let i = 0; i < 2; i++) {
    document.title = `${info.id} ${info.title}`;
    await observeOnce(title, { childList: true });
  }
};
var overrideCss = `
.vim_comic_viewer ::-webkit-scrollbar {
  width: 12px !important;
}
::-webkit-scrollbar-thumb {
  background: #888;
}
`;
var hookReaderPage = async () => {
  await import_vim_comic_viewer2.utils.waitDomContent(document);
  await (0, import_vim_comic_viewer2.initialize)({ source: comicSource, imageProps: { loading: "lazy" } });
  insertCss(overrideCss);
  addEventListener("keypress", onReaderKey);
};
function exec(fn) {
  const script = document.createElement("script");
  script.setAttribute("type", "application/javascript");
  script.textContent = "(" + fn + ")();";
  document.body.appendChild(script);
  document.body.removeChild(script);
}
var initialize2 = async () => {
  const { pathname } = location;
  if (pathname.startsWith("/reader")) {
    await hookReaderPage();
  } else if (!/^\/(manga|doujinshi|cg)\//.test(pathname)) {
    await hookListPage2();
  }
};
initialize2();

});

for (const name of ["@stitches/react","fflate","scheduler","object-assign","react","react-dom","vim_comic_viewer"]) {
  const body = GM_getResourceText(name);
  define(name, Function('require', 'exports', 'module', body));
}

unsafeWindow.process = { env: { NODE_ENV: 'production' } };
require(['main'], () => {}, console.error);