Filters search results by languages and tags
// ==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);