Hitomi - Language & Tag Filtering

Filters search results by languages and tags

2018-12-12 기준 버전입니다. 최신 버전을 확인하세요.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Hitomi - Language & Tag Filtering
// @namespace    brazenvoid
// @version      2.3
// @author       brazenvoid
// @license      GPL-3.0-only
// @description  Filters search results by languages and tags
// @include      https://hitomi.la/*
// @run-at       document-idle
// ==/UserScript==

// Define languages to keep and tags to exclude here 

let settings = {
	allowedLanguages: [
  	"japanese", 
  	"english"
	],
	excludedTags: [
  	"female:loli", 
  	"sample", 
  	"male:yaoi"
	]
};

// Formatting filters

let formatFilters = function (filters, prefix, suffix) {
  
  for (let index = 0; index < filters.length; index++) {
    
  	filters[index] = '[href="'+ prefix + encodeURIComponent(filters[index]) + suffix +'.html"]';
	}
	return filters.join(", ");
};

let languageFiltersSelector = formatFilters(settings.allowedLanguages, "/index-", "-1");
let tagFiltersSelector = formatFilters(settings.excludedTags, "/tag/", "-all-1");

// Filteration logic

let validateLanguage = function (gallery) {
  
  let validationCheck = true;
  
  if (settings.allowedLanguages.length > 0) {
    
    let languageTD = gallery.querySelector('tr:nth-child(3) > td:nth-child(2)');
    if (languageTD.querySelector('a') !== null) {
      validationCheck = languageTD.querySelectorAll(languageFiltersSelector).length > 0;
    }
  }
  return validationCheck;
};

let validateTags = function (gallery) {
  
  let validationCheck = true;
  
  if (settings.excludedTags.length > 0) {    
    validationCheck = gallery.querySelectorAll(tagFiltersSelector).length === 0;
  }
  return validationCheck;
};

let complianceCallback = function(target) {
  
  let galleries = target.querySelectorAll('.manga, .dj, .acg'), removeGallery = false, languageTD;
  
  for (let gallery of galleries) {

    validationCheck = validateLanguage(gallery) && validateTags(gallery);
    
    if (!validationCheck) {
      gallery.remove();
    }
  }
};

// Setting up configuration and galleries list node

let galleriesList = document.querySelector('.gallery-content');
let observerConfig = { 
  attributes: false, 
  childList: true, 
  subtree: false 
};

// Checking compliance in case of gallery page

complianceCallback(galleriesList);

// Adding observer to check compliance of galleries on search pages

let observer = new MutationObserver(function(mutations, observer) {
  for(let mutation of mutations) {
    complianceCallback(mutation.target);
  }
});
observer.observe(galleriesList, observerConfig);