您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Various search filters and user experience enhancers
当前为
// ==UserScript== // @name Hitomi - Search & UI Tweaks // @namespace brazenvoid // @version 4.0.0 // @author brazenvoid // @license GPL-3.0-only // @description Various search filters and user experience enhancers // @match https://hitomi.la/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js // @require https://greasyfork.org/scripts/375557-base-resource/code/Base%20Resource.js?version=889107 // @require https://greasyfork.org/scripts/418665-brazen-configuration-manager/code/Brazen%20Configuration%20Manager.js?version=889083 // @require https://greasyfork.org/scripts/416104-brazen-ui-generator/code/Brazen%20UI%20Generator.js?version=889085 // @require https://greasyfork.org/scripts/416105-brazen-base-search-enhancer/code/Brazen%20Base%20Search%20Enhancer.js?version=890597 // @grant GM_addStyle // @run-at document-end // ==/UserScript== GM_addStyle( `#settings-wrapper{font-family:Open Sans;font-size:12px;font-weight:700;line-height:1;background-color:rgb(216, 210, 234);top:5vh;width:300px} #settings-wrapper button{font-family:Open Sans;font-size:12px;font-weight:700} #settings-wrapper textarea.form-input{height:25vh;line-height:2;overflow:auto;padding:0 10px;resize:vertical;white-space:pre;width:92%} .bg-brand{background-color:rgb(216, 210, 234)}`) const PAGE_PATH_NAME = window.location.pathname const IS_GALLERY_PAGE = $('#dl-button').length const FILTER_GALLERY_TYPES = 'Show Gallery Types' const FILTER_TAG_BLACKLIST = 'Tag Blacklist' const FILTER_LANGUAGES = 'Languages' const OPTION_REMOVE_RELATED_GALLERIES = 'Remove Related Galleries' const SCRIPT_PREFIX = 'hitomi-sui-' const SELECTOR_ITEM = '.acg,.anime,.cg,.dj,.manga' class HitomiSearchAndUITweaks extends BrazenBaseSearchEnhancer { constructor () { super(SCRIPT_PREFIX, SELECTOR_ITEM) this._configurationManager. addCheckboxesGroup(FILTER_GALLERY_TYPES, [ ['Anime', 'anime'], ['Artist CG', 'acg'], ['Doujinshi', 'dj'], ['Game CG', 'cg'], ['Manga', 'manga'], ], 'Show only selected gallery types.'). addCheckboxesGroup(FILTER_LANGUAGES, [ ['N/A', 'not-applicable'], ['Japanese', 'japanese'], ['Chinese', 'chinese'], ['English', 'english'], ['Albanian', 'albanian'], ['Arabic', 'arabic'], ['Bulgarian', 'bulgarian'], ['Catalan', 'catalan'], ['Cebuano', 'cebuano'], ['Czech', 'czech'], ['Danish', 'danish'], ['Dutch', 'dutch'], ['Esperanto', 'esperanto'], ['Estonian', 'estonian'], ['Finnish', 'finnish'], ['French', 'french'], ['German', 'german'], ['Greek', 'greek'], ['Hebrew', 'hebrew'], ['Hungarian', 'hungarian'], ['Indonesian', 'indonesian'], ['Italian', 'italian'], ['Korean', 'korean'], ['Latin', 'latin'], ['Mongolian', 'mongolian'], ['Norwegian', 'norwegian'], ['Persian', 'persian'], ['Polish', 'polish'], ['Portuguese', 'portuguese'], ['Romanian', 'romanian'], ['Russian', 'russian'], ['Slovak', 'slovak'], ['Spanish', 'spanish'], ['Swedish', 'swedish'], ['Tagalog', 'tagalog'], ['Thai', 'thai'], ['Turkish', 'turkish'], ['Ukrainian', 'ukrainian'], ['Unspecified', 'unspecified'], ['Vietnamese', 'vietnamese'], ], 'Select languages to show'). addFlagField(OPTION_REMOVE_RELATED_GALLERIES, 'Remove related galleries section from gallery pages.'). addRulesetField( FILTER_TAG_BLACKLIST, 'Specify the tags blacklist with one rule on each line. While single tags can be specified, complex multi-tag rules with & (AND) and | (OR) can also be defined.', null, null, (blacklistedTags) => this._optimizeBlacklistRules(blacklistedTags)) this._setupUI() this._setupCompliance() this._setupComplianceFilters() } /** * @param {string} tag * @return {JQuery.Selector} * @private */ _formatTagSelector (tag) { return 'a[href$="' + encodeURIComponent(tag.trim()) + '-all.html"]' } /** * @param {string[][]} ruleset * @param {string[]} tags * @return {string[][]} * @private */ _growBlacklistRuleset (ruleset, tags) { let grownRuleset = [] for (let tag of tags) { for (let rule of ruleset) { grownRuleset.push([...rule, this._formatTagSelector(tag)]) } } return grownRuleset } /** * @private */ _optimizeBlacklistRules (blacklistedRules) { let orTags, iteratedRuleset let optimizedRuleset = [] // Translate user defined rules for (let blacklistedRule of blacklistedRules) { iteratedRuleset = [] for (let andTag of blacklistedRule.split('&')) { orTags = andTag.split('|') if (orTags.length === 1) { this._updateBlacklistRuleset(iteratedRuleset, andTag) } else { if (iteratedRuleset.length) { iteratedRuleset = this._growBlacklistRuleset(iteratedRuleset, orTags) } else { this._updateBlacklistRuleset(iteratedRuleset, orTags) } } } optimizedRuleset = optimizedRuleset.concat(iteratedRuleset) } // Sort rules by complexity return optimizedRuleset.sort((a, b) => a.length - b.length) } /** * @private */ _removeRelatedGalleries () { if (IS_GALLERY_PAGE && this._configurationManager.getValue(OPTION_REMOVE_RELATED_GALLERIES)) { $('.gallery-content').remove() } } /** * @private */ _setupCompliance () { this._onGetItemLists = () => $('.gallery-content') this._onGetItemName = (item) => item.find('h1.lillie a').text() } /** * @private */ _setupComplianceFilters () { this._addItemComplianceFilter(FILTER_LANGUAGES, (valueKeys) => valueKeys.length, (item, valueKeys) => { let languageLink = item.find('tr:nth-child(3) > td:nth-child(2) a') if (languageLink.length) { languageLink = languageLink.attr('href') for (let key of valueKeys) { if (languageLink.includes(key)) { return true } } return false } return valueKeys.includes('not-applicable') }) this._addItemComplianceFilter(FILTER_GALLERY_TYPES, (valueKeys) => valueKeys.length, (item, valueKeys) => { for (let galleryClass of valueKeys) { if (item.hasClass(galleryClass)) { return true } } return false }) this._addItemComplianceFilter( FILTER_TAG_BLACKLIST, (blacklistedTags) => blacklistedTags.length, (item, blacklistRuleset) => { let isBlacklisted let itemTagsSection = item.find('.relatedtags') for (let rule of blacklistRuleset) { isBlacklisted = true for (let tagSelector of rule) { if (itemTagsSection.find(tagSelector).length !== 1) { isBlacklisted = false break } } if (isBlacklisted) { return false } } return true } ) } /** * @private */ _setupUI () { this._onBeforeUIBuild = () => { if (IS_GALLERY_PAGE) { this._removeRelatedGalleries() } } this._onUIBuild = () => this._uiGen.createSettingsSection().append([ this._uiGen.createTabsSection(['Filters', 'Languages', 'Global', 'Stats'], [ this._uiGen.createTabPanel('Filters', true).append([ this._configurationManager.createElement(FILTER_GALLERY_TYPES), this._uiGen.createSeparator(), this._configurationManager.createElement(FILTER_TAG_BLACKLIST), this._uiGen.createSeparator(), this._configurationManager.createElement(OPTION_DISABLE_COMPLIANCE_VALIDATION), ]), this._uiGen.createTabPanel('Languages').append([ this._configurationManager.createElement(FILTER_LANGUAGES), ]), this._uiGen.createTabPanel('Global').append([ this._configurationManager.createElement(OPTION_ALWAYS_SHOW_SETTINGS_PANE), this._uiGen.createSeparator(), this._createSettingsBackupRestoreFormActions(), ]), this._uiGen.createTabPanel('Stats').append([ this._uiGen.createStatisticsFormGroup(FILTER_GALLERY_TYPES), this._uiGen.createStatisticsFormGroup(FILTER_LANGUAGES), this._uiGen.createStatisticsFormGroup(FILTER_TAG_BLACKLIST), this._uiGen.createSeparator(), this._uiGen.createStatisticsTotalsGroup(), ]), ]), this._createSettingsFormActions(), this._uiGen.createSeparator(), this._uiGen.createStatusSection(), ]) this._onAfterUIBuild = () => { this._uiGen.getSelectedSection()[0].userScript = this } } /** * @param {string[][]} ruleset * @param {string|string[]} tagToAdd * @private */ _updateBlacklistRuleset (ruleset, tagToAdd) { if (ruleset.length) { for (let rule of ruleset) { rule.push(this._formatTagSelector(tagToAdd)) } } else { let tags = typeof tagToAdd === 'string' ? [tagToAdd] : tagToAdd for (let tag of tags) { ruleset.push([this._formatTagSelector(tag)]) } } } } (new HitomiSearchAndUITweaks).init()