Skip to content

Instantly share code, notes, and snippets.

@simonzack
Last active June 1, 2021 18:51
Show Gist options
  • Save simonzack/d5ac206f0fe661cc0c27 to your computer and use it in GitHub Desktop.
Save simonzack/d5ac206f0fe661cc0c27 to your computer and use it in GitHub Desktop.
google search filter plus
// ==UserScript==
// @name Google Search Filter Plus
// @description Filters google search results
// @namespace smk
// @license MPL 1.1; http://www.mozilla.org/MPL/MPL-1.1.html
// @include http://www.google.tld/
// @include http://www.google.tld/?*
// @include http://www.google.tld/#*&q=*
// @include http://www.google.tld/#q=*
// @include http://www.google.tld/cse?*
// @include http://cse.google.tld/cse?*
// @include http://www.google.tld/custom?*
// @include http://www.google.tld/search?*
// @include https://encrypted.google.com/
// @include https://encrypted.google.com/#*&q=*
// @include https://encrypted.google.com/search?*
// @include https://www.google.tld/
// @include https://www.google.tld/?*
// @include https://www.google.tld/#*&q=*
// @include https://www.google.tld/#q=*
// @include https://www.google.tld/cse?*
// @include https://cse.google.tld/cse?*
// @include https://www.google.tld/custom?*
// @include https://www.google.tld/search?*
// @grant GM_addStyle
// @grant GM_getResourceText
// @grant GM_getResourceURL
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @require https://cdn.jsdelivr.net/jquery/2.1.3/jquery.min.js
// @require https://cdn.jsdelivr.net/jquery.ui/1.11.3/jquery-ui.min.js
// @require https://cdn.jsdelivr.net/jquery.event.drag/2.2/jquery.event.drag.min.js
// @require https://rawgit.com/6pac/SlickGrid/2.1.0/slick.core.js
// @require https://rawgit.com/6pac/SlickGrid/master/slick.editors.js
// @require https://rawgit.com/6pac/SlickGrid/2.1.0/slick.grid.js
// @require https://rawgit.com/6pac/SlickGrid/2.1.0/plugins/slick.rowselectionmodel.js
// @resource jquery-ui-css https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/jquery-ui.min.css
// @resource jquery-ui-css/images/ui-bg_glass_55_fbf9ee_1x400.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
// @resource jquery-ui-css/images/ui-bg_glass_65_ffffff_1x400.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
// @resource jquery-ui-css/images/ui-bg_glass_75_dadada_1x400.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png
// @resource jquery-ui-css/images/ui-bg_glass_75_e6e6e6_1x400.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
// @resource jquery-ui-css/images/ui-bg_glass_95_fef1ec_1x400.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
// @resource jquery-ui-css/images/ui-bg_highlight-soft_75_cccccc_1x100.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
// @resource jquery-ui-css/images/ui-icons_222222_256x240.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-icons_222222_256x240.png
// @resource jquery-ui-css/images/ui-icons_2e83ff_256x240.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-icons_2e83ff_256x240.png
// @resource jquery-ui-css/images/ui-icons_454545_256x240.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-icons_454545_256x240.png
// @resource jquery-ui-css/images/ui-icons_888888_256x240.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-icons_888888_256x240.png
// @resource jquery-ui-css/images/ui-icons_cd0a0a_256x240.png https://cdn.jsdelivr.net/jquery.ui/1.11.3/themes/smoothness/images/ui-icons_cd0a0a_256x240.png
// @resource slickgrid-css https://rawgit.com/6pac/SlickGrid/2.1.0/slick.grid.css
// @resource slickgrid-css/images/sort-asc.gif https://rawgit.com/6pac/SlickGrid/2.1.0/images/sort-asc.gif
// @resource slickgrid-css/images/sort-desc.gif https://rawgit.com/6pac/SlickGrid/2.1.0/images/sort-desc.gif
// ==/UserScript==
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./gfp/lib/filterClasses.js":
/*!**********************************!*\
!*** ./gfp/lib/filterClasses.js ***!
\**********************************/
/*! default exports */
/*! export ActiveFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export BlockingFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export CommentFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export Filter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export InvalidFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export RegExpFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export WhitelistFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_exports__, __webpack_require__ */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-2015 Eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @fileOverview Definition of Filter class and its subclasses.
*/
const { FilterNotifier } = __webpack_require__(/*! ./filterNotifier */ "./gfp/lib/filterNotifier.js")
/**
* Abstract base class for filters
*
* @param {String} text string representation of the filter
* @constructor
*/
function Filter(text) {
this.text = text
this.subscriptions = []
}
exports.Filter = Filter
Filter.prototype = {
/**
* String representation of the filter
* @type String
*/
text: null,
/**
* Filter subscriptions the filter belongs to
* @type Array of Subscription
*/
subscriptions: null,
/**
* Serializes the filter to an array of strings for writing out on the disk.
* @param {Array<String>} buffer buffer to push the serialization results into
*/
serialize: function (buffer) {
buffer.push('[Filter]')
buffer.push('text=' + this.text)
},
toString: function () {
return this.text
},
}
/**
* Cache for known filters, maps string representation to filter objects.
* @type Object
*/
Filter.knownFilters = Object.create(null)
/**
* Regular expression that element hiding filters should match
* @type RegExp
*/
Filter.elemhideRegExp = /^([^/*|@"!]*?)#(@)?(?:([\w-]+|\*)((?:\([\w-]+(?:[$^*]?=[^()"]*)?\))*)|#([^{}]+))$/
/**
* Regular expression that RegExp filters specified as RegExps should match
* @type RegExp
*/
Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^,\s]+)?)*)?$/
/**
* Regular expression that options on a RegExp filter should match
* @type RegExp
*/
Filter.optionsRegExp = /\$(~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^,\s]+)?)*)$/
/**
* Creates a filter of correct type from its text representation - does the basic parsing and
* calls the right constructor then.
*
* @param {String} text as in Filter()
* @return {Filter}
*/
Filter.fromText = function (text) {
if (text in Filter.knownFilters) return Filter.knownFilters[text]
let ret
if (text[0] === '!') ret = new CommentFilter(text)
else ret = RegExpFilter.fromText(text)
Filter.knownFilters[ret.text] = ret
return ret
}
/**
* Deserializes a filter
*
* @param {Object} obj map of serialized properties and their values
* @return {Filter} filter or null if the filter couldn't be created
*/
Filter.fromObject = function (obj) {
const ret = Filter.fromText(obj.text)
if (ret instanceof ActiveFilter) {
if ('disabled' in obj) ret._disabled = obj.disabled === 'true'
if ('hitCount' in obj) ret._hitCount = parseInt(obj.hitCount) || 0
if ('lastHit' in obj) ret._lastHit = parseInt(obj.lastHit) || 0
}
return ret
}
/**
* Removes unnecessary whitespaces from filter text, will only return null if
* the input parameter is null.
*/
Filter.normalize = function (/**String*/ text /**String*/) {
if (!text) return text
// Remove line breaks and such
text = text.replace(/[^\S ]/g, '')
if (/^\s*!/.test(text)) {
// Don't remove spaces inside comments
return text.trim()
} else if (Filter.elemhideRegExp.test(text)) {
// Special treatment for element hiding filters, right side is allowed to contain spaces
const [, domain, separator, selector] = /^(.*?)(#@?#?)(.*)$/.exec(text)
return domain.replace(/\s/g, '') + separator + selector.trim()
} else return text.replace(/\s/g, '')
}
/**
* Class for invalid filters
* @param {String} text see Filter()
* @param {String} reason Reason why this filter is invalid
* @constructor
* @augments Filter
*/
function InvalidFilter(text, reason) {
Filter.call(this, text)
this.reason = reason
}
exports.InvalidFilter = InvalidFilter
InvalidFilter.prototype = {
__proto__: Filter.prototype,
/**
* Reason why this filter is invalid
* @type String
*/
reason: null,
/**
* See Filter.serialize()
*/
serialize: function (_buffer) {},
}
/**
* Class for comments
* @param {String} text see Filter()
* @constructor
* @augments Filter
*/
function CommentFilter(text) {
Filter.call(this, text)
}
exports.CommentFilter = CommentFilter
CommentFilter.prototype = {
__proto__: Filter.prototype,
/**
* See Filter.serialize()
*/
serialize: function (_buffer) {},
}
/**
* Abstract base class for filters that can get hits
* @param {String} text see Filter()
* @param {String} [domains] Domains that the filter is restricted to separated by domainSeparator e.g.
* "foo.com|bar.com|~baz.com"
* @constructor
* @augments Filter
*/
function ActiveFilter(text, domains) {
Filter.call(this, text)
this.domainSource = domains
}
exports.ActiveFilter = ActiveFilter
ActiveFilter.prototype = {
__proto__: Filter.prototype,
_disabled: false,
_hitCount: 0,
_lastHit: 0,
/**
* Defines whether the filter is disabled
* @type Boolean
*/
get disabled() {
return this._disabled
},
set disabled(value) {
if (value !== this._disabled) {
const oldValue = this._disabled
this._disabled = value
FilterNotifier.triggerListeners('filter.disabled', this, value, oldValue)
}
},
/**
* Number of hits on the filter since the last reset
* @type Number
*/
get hitCount() {
return this._hitCount
},
set hitCount(value) {
if (value !== this._hitCount) {
const oldValue = this._hitCount
this._hitCount = value
FilterNotifier.triggerListeners('filter.hitCount', this, value, oldValue)
}
},
/**
* Last time the filter had a hit (in milliseconds since the beginning of the epoch)
* @type Number
*/
get lastHit() {
return this._lastHit
},
set lastHit(value) {
if (value !== this._lastHit) {
const oldValue = this._lastHit
this._lastHit = value
FilterNotifier.triggerListeners('filter.lastHit', this, value, oldValue)
}
},
/**
* String that the domains property should be generated from
* @type String
*/
domainSource: null,
/**
* Separator character used in domainSource property, must be overridden by subclasses
* @type String
*/
domainSeparator: null,
/**
* Determines whether the trailing dot in domain names isn't important and
* should be ignored, must be overridden by subclasses.
* @type Boolean
*/
ignoreTrailingDot: true,
/**
* Determines whether domainSource is already upper-case,
* can be overridden by subclasses.
* @type Boolean
*/
domainSourceIsUpperCase: false,
/**
* Map containing domains that this filter should match on/not match on or null if the filter should match on all
* domains
* @type Object
*/
/* eslint-disable sonarjs/cognitive-complexity */
get domains() {
// Despite this property being cached, the getter is called
// several times on Safari, due to WebKit bug 132872
const prop = Object.getOwnPropertyDescriptor(this, 'domains')
if (prop) return prop.value
let domains = null
if (this.domainSource) {
let source = this.domainSource
if (!this.domainSourceIsUpperCase) {
// RegExpFilter already have uppercase domains
source = source.toUpperCase()
}
const list = source.split(this.domainSeparator)
if (list.length === 1 && list[0][0] !== '~') {
// Fast track for the common one-domain scenario
domains = { __proto__: null, '': false }
if (this.ignoreTrailingDot) list[0] = list[0].replace(/\.+$/, '')
domains[list[0]] = true
} else {
let hasIncludes = false
for (let i = 0; i < list.length; i++) {
let domain = list[i]
if (this.ignoreTrailingDot) domain = domain.replace(/\.+$/, '')
if (domain === '') continue
let include
if (domain[0] === '~') {
include = false
domain = domain.substr(1)
} else {
include = true
hasIncludes = true
}
if (!domains) domains = Object.create(null)
domains[domain] = include
}
domains[''] = !hasIncludes
}
this.domainSource = null
}
Object.defineProperty(this, 'domains', { value: domains, enumerable: true })
return this.domains
},
/**
* Array containing public keys of websites that this filter should apply to
* @type Array of String
*/
sitekeys: null,
/**
* Checks whether this filter is active on a domain.
* @param {String} docDomain domain name of the document that loads the URL
* @param {String} [sitekey] public key provided by the document
* @return {Boolean} true in case of the filter being active
*/
isActiveOnDomain: function (docDomain, sitekey) {
// Sitekeys are case-sensitive so we shouldn't convert them to upper-case to avoid false
// positives here. Instead we need to change the way filter options are parsed.
if (this.sitekeys && (!sitekey || this.sitekeys.indexOf(sitekey.toUpperCase()) < 0)) return false
// If no domains are set the rule matches everywhere
if (!this.domains) return true
// If the document has no host name, match only if the filter isn't restricted to specific domains
if (!docDomain) return this.domains['']
if (this.ignoreTrailingDot) docDomain = docDomain.replace(/\.+$/, '')
docDomain = docDomain.toUpperCase()
while (true) {
if (docDomain in this.domains) return this.domains[docDomain]
const nextDot = docDomain.indexOf('.')
if (nextDot < 0) break
docDomain = docDomain.substr(nextDot + 1)
}
return this.domains['']
},
/**
* Checks whether this filter is active only on a domain and its subdomains.
*/
isActiveOnlyOnDomain: function (/**String*/ docDomain /**Boolean*/) {
if (!docDomain || !this.domains || this.domains['']) return false
if (this.ignoreTrailingDot) docDomain = docDomain.replace(/\.+$/, '')
docDomain = docDomain.toUpperCase()
for (const domain in this.domains)
if (
Object.prototype.hasOwnProperty.call(this.domains, domain) &&
this.domains[domain] &&
domain !== docDomain &&
(domain.length <= docDomain.length || domain.indexOf('.' + docDomain) !== domain.length - docDomain.length - 1)
)
return false
return true
},
/**
* See Filter.serialize()
*/
serialize: function (buffer) {
if (this._disabled || this._hitCount || this._lastHit) {
Filter.prototype.serialize.call(this, buffer)
if (this._disabled) buffer.push('disabled=true')
if (this._hitCount) buffer.push('hitCount=' + this._hitCount)
if (this._lastHit) buffer.push('lastHit=' + this._lastHit)
}
},
}
/**
* Abstract base class for RegExp-based filters
* @param {String} text see Filter()
* @param {String} regexpSource filter part that the regular expression should be build from
* @param {Number} [contentType] Content types the filter applies to, combination of values from RegExpFilter.typeMap
* @param {Boolean} [matchCase] Defines whether the filter should distinguish between lower and upper case letters
* @param {String} [domains] Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
* @param {Boolean} [thirdParty] Defines whether the filter should apply to third-party or first-party content only
* @param {String} [sitekeys] Public keys of websites that this filter should apply to
* @constructor
* @augments ActiveFilter
*/
function RegExpFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, sitekeys) {
ActiveFilter.call(this, text, domains, sitekeys)
if (contentType != null) this.contentType = contentType
if (matchCase) this.matchCase = matchCase
if (thirdParty != null) this.thirdParty = thirdParty
if (sitekeys != null) this.sitekeySource = sitekeys
if (regexpSource.length >= 2 && regexpSource[0] === '/' && regexpSource[regexpSource.length - 1] === '/') {
// The filter is a regular expression - convert it immediately to catch syntax errors
const regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), this.matchCase ? '' : 'i')
Object.defineProperty(this, 'regexp', { value: regexp })
} else {
// No need to convert this filter to regular expression yet, do it on demand
this.regexpSource = regexpSource
}
}
exports.RegExpFilter = RegExpFilter
RegExpFilter.prototype = {
__proto__: ActiveFilter.prototype,
/**
* @see ActiveFilter.domainSourceIsUpperCase
*/
domainSourceIsUpperCase: true,
/**
* Number of filters contained, will always be 1 (required to optimize Matcher).
* @type Integer
*/
length: 1,
/**
* @see ActiveFilter.domainSeparator
*/
domainSeparator: '|',
/**
* Expression from which a regular expression should be generated - for delayed creation of the regexp property
* @type String
*/
regexpSource: null,
/**
* Regular expression to be used when testing against this filter
* @type RegExp
*/
get regexp() {
// Despite this property being cached, the getter is called
// several times on Safari, due to WebKit bug 132872
const prop = Object.getOwnPropertyDescriptor(this, 'regexp')
if (prop) return prop.value
// Remove multiple wildcards
const source = this.regexpSource
.replace(/\*+/g, '*') // remove multiple wildcards
.replace(/\^\|$/, '^') // remove anchors following separator placeholder
.replace(/\W/g, '\\$&') // escape special symbols
.replace(/\\\*/g, '.*') // replace wildcards by .*
// process separator placeholders (all ANSI characters but alphanumeric characters and _%.-)
.replace(/\\\^/g, '(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)')
.replace(/^\\\|\\\|/, '^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?') // process extended anchor at expression start
.replace(/^\\\|/, '^') // process anchor at expression start
.replace(/\\\|$/, '$') // process anchor at expression end
.replace(/^(\.\*)/, '') // remove leading wildcards
.replace(/(\.\*)$/, '') // remove trailing wildcards
const regexp = new RegExp(source, this.matchCase ? '' : 'i')
Object.defineProperty(this, 'regexp', { value: regexp })
return regexp
},
/**
* Content types the filter applies to, combination of values from RegExpFilter.typeMap
* @type Number
*/
contentType: 0x7fffffff,
/**
* Defines whether the filter should distinguish between lower and upper case letters
* @type Boolean
*/
matchCase: false,
/**
* Defines whether the filter should apply to third-party or first-party content only. Can be null (apply to all
* content).
* @type Boolean
*/
thirdParty: null,
/**
* String that the sitekey property should be generated from
* @type String
*/
sitekeySource: null,
/**
* Array containing public keys of websites that this filter should apply to
* @type Array of String
*/
get sitekeys() {
// Despite this property being cached, the getter is called
// several times on Safari, due to WebKit bug 132872
const prop = Object.getOwnPropertyDescriptor(this, 'sitekeys')
if (prop) return prop.value
let sitekeys = null
if (this.sitekeySource) {
sitekeys = this.sitekeySource.split('|')
this.sitekeySource = null
}
Object.defineProperty(this, 'sitekeys', {
value: sitekeys,
enumerable: true,
})
return this.sitekeys
},
/**
* Tests whether the URL matches this filter
* @param {String} location URL to be tested
* @param {String} contentType content type identifier of the URL
* @param {String} docDomain domain name of the document that loads the URL
* @param {Boolean} thirdParty should be true if the URL is a third-party request
* @param {String} sitekey public key provided by the document
* @return {Boolean} true in case of a match
*/
matches: function (location, contentType, docDomain, thirdParty, sitekey) {
return (
this.regexp.test(location) &&
(RegExpFilter.typeMap[contentType] & this.contentType) !== 0 &&
(this.thirdParty == null || this.thirdParty === thirdParty) &&
this.isActiveOnDomain(docDomain, sitekey)
)
},
}
// Required to optimize Matcher, see also RegExpFilter.prototype.length
Object.defineProperty(RegExpFilter.prototype, '0', {
get: function () {
return this
},
})
/**
* Creates a RegExp filter from its text representation
* @param {String} text same as in Filter()
*/
/* eslint-disable sonarjs/cognitive-complexity */
RegExpFilter.fromText = function (text) {
let blocking = true
const origText = text
if (text.indexOf('@@') === 0) {
blocking = false
text = text.substr(2)
}
let contentType = null
let matchCase = null
let domains = null
let sitekeys = null
let thirdParty = null
let collapse = null
let options
const match = text.indexOf('$') >= 0 ? Filter.optionsRegExp.exec(text) : null
if (match) {
options = match[1].toUpperCase().split(',')
text = match.input.substr(0, match.index)
for (let option of options) {
let value = null
let separatorIndex = option.indexOf('=')
if (separatorIndex >= 0) {
value = option.substr(separatorIndex + 1)
option = option.substr(0, separatorIndex)
}
option = option.replace(/-/, '_')
if (option in RegExpFilter.typeMap) {
if (contentType == null) contentType = 0
contentType |= RegExpFilter.typeMap[option]
} else if (option[0] === '~' && option.substr(1) in RegExpFilter.typeMap) {
if (contentType == null) contentType = RegExpFilter.prototype.contentType
contentType &= ~RegExpFilter.typeMap[option.substr(1)]
} else if (option === 'MATCH_CASE') matchCase = true
else if (option === '~MATCH_CASE') matchCase = false
else if (option === 'DOMAIN' && typeof value != 'undefined') domains = value
else if (option === 'THIRD_PARTY') thirdParty = true
else if (option === '~THIRD_PARTY') thirdParty = false
else if (option === 'COLLAPSE') collapse = true
else if (option === '~COLLAPSE') collapse = false
else if (option === 'SITEKEY' && typeof value != 'undefined') sitekeys = value
else return new InvalidFilter(origText, 'Unknown option ' + option.toLowerCase())
}
}
if (
!blocking &&
(contentType == null || contentType & RegExpFilter.typeMap.DOCUMENT) &&
(!options || options.indexOf('DOCUMENT') < 0) &&
!/^\|?[\w-]+:/.test(text)
) {
// Exception filters shouldn't apply to pages by default unless they start with a protocol name
if (contentType == null) contentType = RegExpFilter.prototype.contentType
contentType &= ~RegExpFilter.typeMap.DOCUMENT
}
try {
if (blocking)
return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys, collapse)
else return new WhitelistFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys)
} catch (e) {
return new InvalidFilter(origText, e)
}
}
/**
* Maps type strings like "SCRIPT" or "OBJECT" to bit masks
*/
RegExpFilter.typeMap = {
OTHER: 1,
SCRIPT: 2,
IMAGE: 4,
STYLESHEET: 8,
OBJECT: 16,
SUBDOCUMENT: 32,
DOCUMENT: 64,
XBL: 1,
PING: 1,
XMLHTTPREQUEST: 2048,
OBJECT_SUBREQUEST: 4096,
DTD: 1,
MEDIA: 16384,
FONT: 32768,
BACKGROUND: 4, // Backwards compat, same as IMAGE
POPUP: 0x10000000,
ELEMHIDE: 0x40000000,
}
// ELEMHIDE, POPUP option shouldn't be there by default
RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFilter.typeMap.POPUP)
/**
* Class for blocking filters
* @param {String} text see Filter()
* @param {String} regexpSource see RegExpFilter()
* @param {Number} contentType see RegExpFilter()
* @param {Boolean} matchCase see RegExpFilter()
* @param {String} domains see RegExpFilter()
* @param {Boolean} thirdParty see RegExpFilter()
* @param {String} sitekeys see RegExpFilter()
* @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null
* @constructor
* @augments RegExpFilter
*/
function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, sitekeys, collapse) {
RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty, sitekeys)
this.collapse = collapse
}
exports.BlockingFilter = BlockingFilter
BlockingFilter.prototype = {
__proto__: RegExpFilter.prototype,
/**
* Defines whether the filter should collapse blocked content. Can be null (use the global preference).
* @type Boolean
*/
collapse: null,
}
/**
* Class for whitelist filters
* @param {String} text see Filter()
* @param {String} regexpSource see RegExpFilter()
* @param {Number} contentType see RegExpFilter()
* @param {Boolean} matchCase see RegExpFilter()
* @param {String} domains see RegExpFilter()
* @param {Boolean} thirdParty see RegExpFilter()
* @param {String} sitekeys see RegExpFilter()
* @constructor
* @augments RegExpFilter
*/
function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, thirdParty, sitekeys) {
RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, thirdParty, sitekeys)
}
exports.WhitelistFilter = WhitelistFilter
WhitelistFilter.prototype = {
__proto__: RegExpFilter.prototype,
}
/***/ }),
/***/ "./gfp/lib/filterNotifier.js":
/*!***********************************!*\
!*** ./gfp/lib/filterNotifier.js ***!
\***********************************/
/*! default exports */
/*! export FilterNotifier [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_exports__ */
/***/ ((__unused_webpack_module, exports) => {
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-2015 Eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @fileOverview This component manages listeners and calls them to distributes
* messages about filter changes.
*/
/**
* List of registered listeners
* @type Array of function(action, item, newValue, oldValue)
*/
const listeners = []
/**
* This class allows registering and triggering listeners for filter events.
* @class
*/
const _FilterNotifier = (exports.FilterNotifier = {
/**
* Adds a listener
*/
addListener: function (/**function(action, item, newValue, oldValue)*/ listener) {
if (listeners.indexOf(listener) >= 0) return
listeners.push(listener)
},
/**
* Removes a listener that was previosly added via addListener
*/
removeListener: function (/**function(action, item, newValue, oldValue)*/ listener) {
const index = listeners.indexOf(listener)
if (index >= 0) listeners.splice(index, 1)
},
/**
* Notifies listeners about an event
* @param {String} action event code ("load", "save", "elemhideupdate",
* "subscription.added", "subscription.removed",
* "subscription.disabled", "subscription.title",
* "subscription.lastDownload", "subscription.downloadStatus",
* "subscription.homepage", "subscription.updated",
* "filter.added", "filter.removed", "filter.moved",
* "filter.disabled", "filter.hitCount", "filter.lastHit")
* @param {Filter} item item that the change applies to
*/
triggerListeners: function (action, item, param1, param2, param3) {
const list = listeners.slice()
for (const listener of list) listener(action, item, param1, param2, param3)
},
})
/***/ }),
/***/ "./gfp/lib/matcher.js":
/*!****************************!*\
!*** ./gfp/lib/matcher.js ***!
\****************************/
/*! default exports */
/*! export CombinedMatcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! export Matcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! export defaultMatcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_exports__, __webpack_require__ */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-2015 Eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @fileOverview Matcher class implementing matching addresses against a list of filters.
*/
const { Filter, _RegExpFilter, WhitelistFilter } = __webpack_require__(/*! ./filterClasses */ "./gfp/lib/filterClasses.js")
/**
* Blacklist/whitelist filter matching
* @constructor
*/
function Matcher() {
this.clear()
}
exports.Matcher = Matcher
Matcher.prototype = {
/**
* Lookup table for filters by their associated keyword
* @type Object
*/
filterByKeyword: null,
/**
* Lookup table for keywords by the filter text
* @type Object
*/
keywordByFilter: null,
/**
* Removes all known filters
*/
clear: function () {
this.filterByKeyword = Object.create(null)
this.keywordByFilter = Object.create(null)
},
/**
* Adds a filter to the matcher
* @param {RegExpFilter} filter
*/
add: function (filter) {
if (filter.text in this.keywordByFilter) return
// Look for a suitable keyword
const keyword = this.findKeyword(filter)
const oldEntry = this.filterByKeyword[keyword]
if (typeof oldEntry == 'undefined') this.filterByKeyword[keyword] = filter
else if (oldEntry.length === 1) this.filterByKeyword[keyword] = [oldEntry, filter]
else oldEntry.push(filter)
this.keywordByFilter[filter.text] = keyword
},
/**
* Removes a filter from the matcher
* @param {RegExpFilter} filter
*/
remove: function (filter) {
if (!(filter.text in this.keywordByFilter)) return
const keyword = this.keywordByFilter[filter.text]
const list = this.filterByKeyword[keyword]
if (list.length <= 1) delete this.filterByKeyword[keyword]
else {
const index = list.indexOf(filter)
if (index >= 0) {
list.splice(index, 1)
if (list.length === 1) this.filterByKeyword[keyword] = list[0]
}
}
delete this.keywordByFilter[filter.text]
},
/**
* Chooses a keyword to be associated with the filter
* @param {String} text text representation of the filter
* @return {String} keyword (might be empty string)
*/
findKeyword: function (filter) {
let result = ''
let text = filter.text
if (Filter.regexpRegExp.test(text)) return result
// Remove options
const match = Filter.optionsRegExp.exec(text)
if (match) text = match.input.substr(0, match.index)
// Remove whitelist marker
if (text.substr(0, 2) === '@@') text = text.substr(2)
const candidates = text.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g)
if (!candidates) return result
const hash = this.filterByKeyword
let resultCount = 0xffffff
let resultLength = 0
for (let i = 0, l = candidates.length; i < l; i++) {
const candidate = candidates[i].substr(1)
const count = candidate in hash ? hash[candidate].length : 0
if (count < resultCount || (count === resultCount && candidate.length > resultLength)) {
result = candidate
resultCount = count
resultLength = candidate.length
}
}
return result
},
/**
* Checks whether a particular filter is being matched against.
*/
hasFilter: function (/**RegExpFilter*/ filter /**Boolean*/) {
return filter.text in this.keywordByFilter
},
/**
* Returns the keyword used for a filter, null for unknown filters.
*/
getKeywordForFilter: function (/**RegExpFilter*/ filter /**String*/) {
if (filter.text in this.keywordByFilter) return this.keywordByFilter[filter.text]
else return null
},
/**
* Checks whether the entries for a particular keyword match a URL
*/
_checkEntryMatch: function (keyword, location, contentType, docDomain, thirdParty, sitekey) {
const list = this.filterByKeyword[keyword]
for (let i = 0; i < list.length; i++) {
const filter = list[i]
if (filter.matches(location, contentType, docDomain, thirdParty, sitekey)) return filter
}
return null
},
/**
* Tests whether the URL matches any of the known filters
* @param {String} location URL to be tested
* @param {String} contentType content type identifier of the URL
* @param {String} docDomain domain name of the document that loads the URL
* @param {Boolean} thirdParty should be true if the URL is a third-party request
* @param {String} sitekey public key provided by the document
* @return {RegExpFilter} matching filter or null
*/
matchesAny: function (location, contentType, docDomain, thirdParty, sitekey) {
let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g)
if (candidates === null) candidates = []
candidates.push('')
for (let i = 0, l = candidates.length; i < l; i++) {
const substr = candidates[i]
if (substr in this.filterByKeyword) {
const result = this._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey)
if (result) return result
}
}
return null
},
}
/**
* Combines a matcher for blocking and exception rules, automatically sorts
* rules into two Matcher instances.
* @constructor
*/
function CombinedMatcher() {
this.blacklist = new Matcher()
this.whitelist = new Matcher()
this.resultCache = Object.create(null)
}
exports.CombinedMatcher = CombinedMatcher
/**
* Maximal number of matching cache entries to be kept
* @type Number
*/
CombinedMatcher.maxCacheEntries = 1000
CombinedMatcher.prototype = {
/**
* Matcher for blocking rules.
* @type Matcher
*/
blacklist: null,
/**
* Matcher for exception rules.
* @type Matcher
*/
whitelist: null,
/**
* Lookup table of previous matchesAny results
* @type Object
*/
resultCache: null,
/**
* Number of entries in resultCache
* @type Number
*/
cacheEntries: 0,
/**
* @see Matcher#clear
*/
clear: function () {
this.blacklist.clear()
this.whitelist.clear()
this.resultCache = Object.create(null)
this.cacheEntries = 0
},
/**
* @see Matcher#add
*/
add: function (filter) {
if (filter instanceof WhitelistFilter) this.whitelist.add(filter)
else this.blacklist.add(filter)
if (this.cacheEntries > 0) {
this.resultCache = Object.create(null)
this.cacheEntries = 0
}
},
/**
* @see Matcher#remove
*/
remove: function (filter) {
if (filter instanceof WhitelistFilter) this.whitelist.remove(filter)
else this.blacklist.remove(filter)
if (this.cacheEntries > 0) {
this.resultCache = Object.create(null)
this.cacheEntries = 0
}
},
/**
* @see Matcher#findKeyword
*/
findKeyword: function (filter) {
if (filter instanceof WhitelistFilter) return this.whitelist.findKeyword(filter)
else return this.blacklist.findKeyword(filter)
},
/**
* @see Matcher#hasFilter
*/
hasFilter: function (filter) {
if (filter instanceof WhitelistFilter) return this.whitelist.hasFilter(filter)
else return this.blacklist.hasFilter(filter)
},
/**
* @see Matcher#getKeywordForFilter
*/
getKeywordForFilter: function (filter) {
if (filter instanceof WhitelistFilter) return this.whitelist.getKeywordForFilter(filter)
else return this.blacklist.getKeywordForFilter(filter)
},
/**
* Checks whether a particular filter is slow
*/
isSlowFilter: function (/**RegExpFilter*/ filter /**Boolean*/) {
let matcher = filter instanceof WhitelistFilter ? this.whitelist : this.blacklist
if (matcher.hasFilter(filter)) return !matcher.getKeywordForFilter(filter)
else return !matcher.findKeyword(filter)
},
/**
* Optimized filter matching testing both whitelist and blacklist matchers
* simultaneously. For parameters see Matcher.matchesAny().
* @see Matcher#matchesAny
*/
matchesAnyInternal: function (location, contentType, docDomain, thirdParty, sitekey) {
let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g)
if (candidates === null) candidates = []
candidates.push('')
let blacklistHit = null
for (let i = 0, l = candidates.length; i < l; i++) {
const substr = candidates[i]
if (substr in this.whitelist.filterByKeyword) {
const result = this.whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey)
if (result) return result
}
if (substr in this.blacklist.filterByKeyword && blacklistHit === null)
blacklistHit = this.blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey)
}
return blacklistHit
},
/**
* @see Matcher#matchesAny
*/
matchesAny: function (location, contentType, docDomain, thirdParty, sitekey) {
const key = location + ' ' + contentType + ' ' + docDomain + ' ' + thirdParty + ' ' + sitekey
if (key in this.resultCache) return this.resultCache[key]
const result = this.matchesAnyInternal(location, contentType, docDomain, thirdParty, sitekey)
if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) {
this.resultCache = Object.create(null)
this.cacheEntries = 0
}
this.resultCache[key] = result
this.cacheEntries++
return result
},
}
/**
* Shared CombinedMatcher instance that should usually be used.
* @type CombinedMatcher
*/
const _defaultMatcher = (exports.defaultMatcher = new CombinedMatcher())
/***/ }),
/***/ "./gfp/plugin sync recursive ^\\.\\/.*$":
/*!***********************************!*\
!*** ./gfp/plugin/ sync ^\.\/.*$ ***!
\***********************************/
/*! default exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.o, __webpack_require__ */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
var map = {
"./autopagerize": "./gfp/plugin/autopagerize.js",
"./autopagerize.js": "./gfp/plugin/autopagerize.js",
"./customsearch": "./gfp/plugin/customsearch.js",
"./customsearch.js": "./gfp/plugin/customsearch.js",
"./google": "./gfp/plugin/google.js",
"./google.js": "./gfp/plugin/google.js",
"./instant": "./gfp/plugin/instant.js",
"./instant.js": "./gfp/plugin/instant.js"
};
function webpackContext(req) {
var id = webpackContextResolve(req);
return __webpack_require__(id);
}
function webpackContextResolve(req) {
if(!__webpack_require__.o(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return map[req];
}
webpackContext.keys = function webpackContextKeys() {
return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = "./gfp/plugin sync recursive ^\\.\\/.*$";
/***/ }),
/***/ "./gfp/bin/main.js":
/*!*************************!*\
!*** ./gfp/bin/main.js ***!
\*************************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../config */ "./gfp/config.js");
/* harmony import */ var _pref__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../pref */ "./gfp/pref.js");
/* harmony import */ var _logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../logger */ "./gfp/logger.js");
function main() {
_logger__WEBPACK_IMPORTED_MODULE_2__.LogTime.start();
const config = new _config__WEBPACK_IMPORTED_MODULE_0__.default(); // es5 to allow webpack to parse requires
let searchGui = null;
for (let i = 0; i < config.plugins.length; i++) {
searchGui = __webpack_require__("./gfp/plugin sync recursive ^\\.\\/.*$")("./" + config.plugins[i]).default(searchGui, config);
}
new _pref__WEBPACK_IMPORTED_MODULE_1__.default(searchGui);
_logger__WEBPACK_IMPORTED_MODULE_2__.LogTime.snap('Total init time');
}
main();
/***/ }),
/***/ "./gfp/config.js":
/*!***********************!*\
!*** ./gfp/config.js ***!
\***********************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => /* binding */ Config
/* harmony export */ });
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ "./gfp/filter.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./gfp/utils.js");
class Filters {
constructor(filters) {
this._comparer = (x, y) => x['text'] > y['text'] ? 1 : x['text'] < y['text'] ? -1 : 0;
this._filters = filters.sort(this._comparer);
this._callbacks = [];
}
get length() {
return this._filters.length;
}
[Symbol.iterator]() {
return this._filters[Symbol.iterator]();
}
_trigger(type, value) {
for (const cb of this._callbacks) {
cb(type, value);
}
}
add(filter) {
this._filters.splice((0,_utils__WEBPACK_IMPORTED_MODULE_1__.bisect)(this._filters, filter, this._comparer), 0, filter);
this._trigger('add', filter);
}
remove(filters) {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.popMany)(this._filters, (0,_utils__WEBPACK_IMPORTED_MODULE_1__.indexOfSorted)(this._filters, filters.sort(this._comparer), this._comparer));
this._trigger('remove', filters);
}
update(filter) {
this._trigger('update', filter);
}
setValue(filters) {
this._filters = filters.sort(this._comparer);
this._trigger('setValue', filters);
}
observe(cb) {
this._callbacks.push(cb);
}
unobserve(cb) {
this._callbacks.splice(this._callbacks.indexOf(cb), 1);
}
}
class Config {
constructor() {
this.plugins = ['google', 'customsearch', 'instant', 'autopagerize'];
this.allowHidden = GM_getValue('allowHidden', true);
this.filtersObject = JSON.parse(GM_getValue('filters', '{}'));
const filters = [];
for (const key in this.filtersObject) {
if (Object.prototype.hasOwnProperty.call(this.filtersObject, key)) {
filters.push(_filter__WEBPACK_IMPORTED_MODULE_0__.Filter.fromObject(key, this.filtersObject[key]));
}
}
this.filters = new Filters(filters);
this.filters.observe((type, value) => {
switch (type) {
case 'add':
this.filtersObject[value.text] = value.toObject();
break;
case 'remove':
for (const filter of value) {
delete this.filtersObject[filter.text];
}
break;
case 'update':
this.filtersObject[value.text] = value.toObject();
break;
case 'setValue':
this.filtersObject = {};
for (const filter of value) {
this.filtersObject[filter.text] = filter.toObject();
}
break;
}
});
}
flushAllowHidden() {
GM_setValue('allowHidden', this.allowHidden);
}
flushFilters() {
GM_setValue('filters', JSON.stringify(this.filtersObject));
}
}
/***/ }),
/***/ "./gfp/filter.js":
/*!***********************!*\
!*** ./gfp/filter.js ***!
\***********************/
/*! namespace exports */
/*! export BlockingFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export Filter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export MultiRegExpFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export RegExpFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! export WhitelistFilter [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "RegExpFilter": () => /* binding */ RegExpFilter,
/* harmony export */ "MultiRegExpFilter": () => /* binding */ MultiRegExpFilter,
/* harmony export */ "Filter": () => /* binding */ Filter,
/* harmony export */ "BlockingFilter": () => /* binding */ BlockingFilter,
/* harmony export */ "WhitelistFilter": () => /* binding */ WhitelistFilter
/* harmony export */ });
/* harmony import */ var _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/filterClasses */ "./gfp/lib/filterClasses.js");
const RegExpFilter__ = Object.assign(new Function(), _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.RegExpFilter, {
prototype: _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.RegExpFilter.prototype
});
class RegExpFilter extends RegExpFilter__ {
constructor(regexpSource, matchCase, collapse) {
super();
if (matchCase) {
this.matchCase = matchCase;
}
if (collapse) {
this.collapse = collapse;
} // convert regex filters immediately to catch syntax errors, normal filters on-demand
if (regexpSource.length >= 2 && regexpSource.startsWith('/') && regexpSource.endsWith('/')) {
const regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), this.matchCase ? '' : 'i');
Object.defineProperty(this, 'regexp', {
value: regexp
});
} else {
this.regexpSource = regexpSource;
}
}
matches(data) {
return this.regexp.test(data);
}
static fromParts(text, optionsStr = '') {
// text is not stored to save memory
let matchCase = false;
let collapse = false;
const options = optionsStr.toUpperCase().split(',');
for (const option of options) {
switch (option) {
case 'MATCH_CASE':
matchCase = true;
break;
case 'COLLAPSE':
collapse = true;
break;
case '':
break;
default:
return new _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.InvalidFilter(`Unknown option: ${option}`);
}
}
return new RegExpFilter(text, matchCase, collapse);
}
*[Symbol.iterator]() {
yield this;
}
}
RegExpFilter.prototype.matchCase = false;
RegExpFilter.prototype.collapse = false; // index to all subfilters
RegExpFilter.prototype.index = 0; // index to all non-null subfilters
RegExpFilter.prototype.dataIndex = 0;
const ActiveFilter_ = Object.assign(new Function(), _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.ActiveFilter, {
prototype: _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.RegExpFilter.prototype
});
class MultiRegExpFilter extends ActiveFilter_ {
constructor(text, filters) {
super();
this.text = text;
this.filters = filters;
for (const filter of filters) {
filter.parent = this;
}
}
get collapse() {
for (const filter of this.filters) {
if (filter.collapse) {
return true;
}
}
return false;
}
static fromText(text) {
const origText = text;
let filters = [];
let blocking = true;
if (text.indexOf('@@') === 0) {
blocking = false;
text = text.substr(2);
}
const parts = text.split(/\$([\w,]*?)(?:\$|$)/);
for (let i = 0; i < parts.length; i += 2) {
const [part, options] = [parts[i], parts[i + 1]];
if (!part) {
continue;
}
const filter = RegExpFilter.fromParts(part, options);
if (filter instanceof _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.InvalidFilter) {
return new _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.InvalidFilter(text);
}
if (i > 0) {
filter.index = i / 2;
}
if (filters.length > 0) {
filter.dataIndex = filters.length;
}
filters.push(filter);
}
if (filters.length === 1) {
filters = filters[0];
}
return blocking ? new BlockingFilter(origText, filters) : new WhitelistFilter(origText, filters);
}
}
const Filter = _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.Filter;
Filter.fromObject = function (text, obj) {
const res = Filter.fromText(text);
if (res instanceof _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.ActiveFilter) {
if ('disabled' in obj) {
res._disabled = obj.disabled === true;
}
if ('hitCount' in obj) {
res._hitCount = parseInt(obj.hitCount) || 0;
}
if ('lastHit' in obj) {
res._lastHit = parseInt(obj.lastHit) || null;
}
}
return res;
};
Filter.prototype.toObject = function () {
const res = {};
if (this instanceof _lib_filterClasses__WEBPACK_IMPORTED_MODULE_0__.ActiveFilter) {
if (this._disabled) {
res.disabled = true;
}
if (this._hitCount) {
res.hitCount = this._hitCount;
}
if (this._lastHit) {
res.lastHit = this._lastHit;
}
}
return res;
};
Filter.fromText = MultiRegExpFilter.fromText;
class BlockingFilter extends MultiRegExpFilter {}
class WhitelistFilter extends MultiRegExpFilter {}
/***/ }),
/***/ "./gfp/gui.js":
/*!********************!*\
!*** ./gfp/gui.js ***!
\********************/
/*! namespace exports */
/*! export NodeData [provided] [no usage info] [missing usage info prevents renaming] */
/*! export SearchGui [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "NodeData": () => /* binding */ NodeData,
/* harmony export */ "SearchGui": () => /* binding */ SearchGui
/* harmony export */ });
/* harmony import */ var _css_gui_sass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./css/gui.sass */ "./gfp/css/gui.sass");
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./filter */ "./gfp/filter.js");
/* harmony import */ var _matcher__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./matcher */ "./gfp/matcher.js");
class NodeData {
constructor(node) {
this.node = node;
}
act(action, filter) {
// action: function which modifies the node
if (this.action === action) {
this.redo(filter);
return true;
} else {
this.undo();
delete this.redo;
delete this.undo;
}
this.action = action;
}
*getChildren() {}
redo() {} // re-apply action with different arguments
undo() {} // undo action
}
NodeData.attrs = ['url', 'title', 'summary'];
NodeData.prototype.linkArea = null;
NodeData.prototype.url = null;
NodeData.prototype.title = null;
NodeData.prototype.summary = null;
NodeData.prototype.action = null;
class SearchGui {
constructor(ResultsData, config) {
this.ResultsData = ResultsData;
this.config = config;
const observer = (type, value) => {
switch (type) {
case 'add':
this.matcher.add(value);
break;
case 'remove':
for (const filter of value) {
this.matcher.remove(filter);
}
break;
case 'setValue':
this.matcher = new _matcher__WEBPACK_IMPORTED_MODULE_2__.CombinedMultiMatcher(NodeData.attrs.length);
for (const filter of value) {
this.matcher.add(filter);
}
break;
}
};
observer('setValue', this.config.filters);
this.config.filters.observe(observer);
this.nodeData = new NodeData();
this.nodeData.children = [];
this.createNodes();
GM_addStyle(_css_gui_sass__WEBPACK_IMPORTED_MODULE_0__.default.toString());
}
createNodes() {
/**
Create once and clone to improve performance.
*/
// add filter link
this.addLink = document.createElement('a');
this.addLink.textContent = 'Filter';
this.addLink.setAttribute('href', '#');
this.addLink.classList.add('filter-add'); // hidden result title
this.showTitle = document.createElement('span');
this.showTitle.classList.add('show-title'); // hidden result 'show' link
this.showLink = document.createElement('a');
this.showLink.textContent = 'show';
this.showLink.setAttribute('href', '#');
this.showLink.classList.add('show-link');
}
toggleResult(nodeData, showTitle, showLink, initial = false) {
for (const child of nodeData.node.children) {
if (child !== showTitle && child !== showLink) {
child.classList.toggle('hide');
}
}
if (initial) {
return;
}
if (showTitle) {
showTitle.classList.toggle('hide');
}
showLink.classList.toggle('hide');
showLink.textContent = showLink.classList.contains('hide') ? 'hide' : 'show';
}
hideResult(nodeData, filter = null) {
if (!nodeData.node || nodeData.act(this.hideResult, filter)) {
return;
}
if (this.config.allowHidden && (!filter || filter.collapse)) {
nodeData.node.classList.add('hide');
nodeData.undo = () => nodeData.node.classList.remove('hide');
return;
}
let showTitle = null;
if (nodeData.title !== null) {
showTitle = this.showTitle.cloneNode(false);
showTitle.textContent = nodeData.title;
nodeData.node.appendChild(showTitle);
}
const showLink = this.showLink.cloneNode(true);
if (filter) {
showLink.title = filter.text;
}
nodeData.node.appendChild(showLink);
this.toggleResult(nodeData, showTitle, showLink, true);
showLink.onclick = () => {
this.toggleResult(nodeData, showTitle, showLink);
return false;
};
nodeData.redo = filter => {
if (filter) {
showLink.title = filter.text;
}
};
nodeData.undo = () => {
if (!showLink.classList.contains('hide')) {
this.toggleResult(nodeData, showTitle, showLink);
}
if (showTitle) {
showTitle.remove();
}
showLink.remove();
};
}
addFilterLink(nodeData, filter = null) {
if (!nodeData.node || nodeData.act(this.addFilterLink, filter)) {
return;
}
if (!nodeData.linkArea) {
return;
}
const addLink = this.addLink.cloneNode(true);
if (filter) {
addLink.title = filter.text;
}
nodeData.linkArea.appendChild(addLink);
addLink.onclick = () => {
this.addFromResult(nodeData);
return false;
};
nodeData.redo = filter => {
if (filter) {
addLink.title = filter.text;
}
};
nodeData.undo = () => {
addLink.remove();
};
}
addFromResult(nodeData) {
const domainUrl = '||' + nodeData.url.replace(/^[\w-]+:\/+(?:www\.)?/, '');
const text = prompt('Filter: ', domainUrl);
if (text === null) {
return;
}
this.config.filters.add(_filter__WEBPACK_IMPORTED_MODULE_1__.MultiRegExpFilter.fromText(text));
this.filterResults();
}
_filterResults(nodeData) {
// store all children so we can re-filter
if (nodeData.children === undefined) {
nodeData.children = Array.from(nodeData.getChildren());
}
const filter = this.matcher.matchesAny(nodeData, NodeData.attrs);
if (filter) {
filter.hitCount++;
filter.lastHit = new Date().getTime();
this.config.filters.update(filter);
if (filter instanceof _filter__WEBPACK_IMPORTED_MODULE_1__.BlockingFilter) {
this.hideResult(nodeData, filter);
return true;
} else {
this.addFilterLink(nodeData, filter);
return false;
}
}
let filtered = !!nodeData.children.length;
for (const childData of nodeData.children) {
if (childData.node.querySelector('a.filter-add')) {
continue;
}
if (!this._filterResults(childData)) {
filtered = false;
}
}
if (filtered) {
this.hideResult(nodeData);
} else if (NodeData.attrs.some(attr => nodeData[attr] !== null)) {
this.addFilterLink(nodeData);
}
return filtered;
}
filterResults(node = null) {
/**
args:
node: Used when additional search results pop up.
*/
let matched = false;
const observer = (type, _filter) => {
if (type === 'update') {
matched = true;
}
};
this.config.filters.observe(observer);
if (node) {
// only need to filter the new node
const nodeData = new this.ResultsData(node);
this.nodeData.children.push(nodeData);
this._filterResults(nodeData);
} else {
this._filterResults(this.nodeData);
}
if (matched) {
this.config.flushFilters();
}
this.config.filters.unobserve(observer);
}
}
/***/ }),
/***/ "./gfp/logger.js":
/*!***********************!*\
!*** ./gfp/logger.js ***!
\***********************/
/*! namespace exports */
/*! export LogTime [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "LogTime": () => /* binding */ LogTime
/* harmony export */ });
const LogTime = {
curTime: null,
start() {
this.curTime = new Date().getTime();
},
snap(msg) {
console.log(`${msg}: ${new Date().getTime() - this.curTime}ms`);
}
};
/***/ }),
/***/ "./gfp/matcher.js":
/*!************************!*\
!*** ./gfp/matcher.js ***!
\************************/
/*! namespace exports */
/*! export CombinedMultiMatcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! export MultiMatcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! export SubMatcher [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SubMatcher": () => /* binding */ SubMatcher,
/* harmony export */ "MultiMatcher": () => /* binding */ MultiMatcher,
/* harmony export */ "CombinedMultiMatcher": () => /* binding */ CombinedMultiMatcher
/* harmony export */ });
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ "./gfp/filter.js");
/* harmony import */ var _lib_matcher__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/matcher */ "./gfp/lib/matcher.js");
class SubMatcher extends _lib_matcher__WEBPACK_IMPORTED_MODULE_1__.Matcher {
static _findCandidates(filter) {
if (filter.regexpSource === null) {
return null;
}
return filter.regexpSource.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g);
}
static isSlowFilter(filter) {
return !this._findCandidates(filter);
}
findKeyword(filter) {
let res = '';
const candidates = this.constructor._findCandidates(filter);
if (candidates === null) {
return res;
}
let resCount = 0xffffff;
let resLength = 0;
for (let candidate of candidates) {
candidate = candidate.substr(1);
const count = this.filterByKeyword.has(candidate) ? this.filterByKeyword.get(candidate).length : 0;
if (count < resCount || count === resCount && candidate.length > resLength) {
res = candidate;
resCount = count;
resLength = candidate.length;
}
}
return res;
}
add(filter) {
// Duplicates are rare and not checked for efficiency, otherwise we need to store sub filter text maps, and multiple
// parents per sub filter.
const keyword = this.findKeyword(filter);
const prevEntry = this.filterByKeyword.get(keyword);
if (prevEntry === undefined) {
this.filterByKeyword.set(keyword, filter);
} else if (prevEntry.length === 1) {
this.filterByKeyword.set(keyword, [prevEntry, filter]);
} else {
prevEntry.push(filter);
}
}
remove(filter) {
// only used by pref, doesn't need to be efficient
const candidates = this.constructor._findCandidates(filter) || [''];
for (let candidate of candidates) {
candidate = candidate.substr(1);
const prevEntry = this.filterByKeyword.get(candidate);
if (prevEntry === undefined) {
continue;
}
if (prevEntry.length === 1) {
if (prevEntry === filter) {
this.filterByKeyword.delete(candidate);
break;
}
continue;
}
const i = prevEntry.indexOf(filter);
if (i === -1) {
if (prevEntry.length === 2) {
this.filterByKeyword.set(candidate, prevEntry[1 - i]);
} else {
prevEntry.splice(i, 1);
}
break;
}
}
}
clear() {
this.filterByKeyword = new Map();
}
hasFilter() {
throw 'not implemented';
}
getKeywordForFilter() {
throw 'not implemented';
}
*_iterMatches(filters, data, parents) {
for (const filter of filters) {
const parent = filter.parent;
if ((filter.dataIndex === 0 || parents.has(parent)) && filter.matches(data)) {
yield filter;
}
}
}
*iterMatches(data, parents) {
/**
args:
parents: All parent filters matched so far, excluding the ones whose subFilters have so far been null.
*/
if (data === null) {
return;
}
let candidates = data.toLowerCase().match(/[a-z0-9%]{3,}/g);
if (candidates === null) {
candidates = [];
}
candidates.push('');
for (const keyword of candidates) {
const filters = this.filterByKeyword.get(keyword);
if (filters) {
for (const res of this._iterMatches(filters, data, parents)) {
yield res;
}
}
}
}
}
class MultiMatcher {
constructor(n) {
this.n = n;
this.matchers = [];
for (let i = 0; i < n; i++) {
this.matchers.push(new SubMatcher());
}
}
static isSlowFilter(filter) {
for (const subFilter of filter.filters) {
if (SubMatcher.isSlowFilter(subFilter)) {
return true;
}
}
return false;
}
add(filter) {
if (filter.disabled) {
return;
}
for (const subFilter of filter.filters) {
this.matchers[subFilter.index].add(subFilter);
}
}
remove(filter) {
for (const subFilter of filter.filters) {
this.matchers[subFilter.index].remove(subFilter);
}
}
clear() {
for (const matcher of this.matchers) {
matcher.clear();
}
}
matchesAny(data, attrs) {
// for each filter, nextNullNum counts how many subfilters there are left until the next non-null subfilter
// {filter: nextNullNum}
let [prevFilters, curFilters] = [new Map(), new Map()];
for (let i = 0; i < this.n; i++) {
for (const subFilter of this.matchers[i].iterMatches(data[attrs[i]], prevFilters)) {
if (subFilter.dataIndex === subFilter.parent.filters.length - 1) {
return subFilter.parent;
}
curFilters.set(subFilter.parent, subFilter.parent.filters[subFilter.dataIndex + 1].index - i);
}
if (i !== this.n - 1) {
// include null subFilters whose parents have so far matched
for (const [filter, nextNullNum] of prevFilters.entries()) {
if (nextNullNum > 0) {
curFilters.set(filter, nextNullNum - 1);
}
}
;
[prevFilters, curFilters] = [curFilters, new Map()];
}
}
return null;
}
}
class CombinedMultiMatcher {
constructor(n) {
// caching is not required since we have one instance per tab, and past filter results are easily accessible
this.blacklist = new MultiMatcher(n);
this.whitelist = new MultiMatcher(n);
}
static isSlowFilter(filter) {
return MultiMatcher.isSlowFilter(filter);
}
add(filter) {
if (filter instanceof _filter__WEBPACK_IMPORTED_MODULE_0__.WhitelistFilter) {
this.whitelist.add(filter);
} else {
this.blacklist.add(filter);
}
}
remove(filter) {
if (filter instanceof _filter__WEBPACK_IMPORTED_MODULE_0__.WhitelistFilter) {
this.whitelist.remove(filter);
} else {
this.blacklist.remove(filter);
}
}
clear() {
this.blacklist.clear();
this.whitelist.clear();
}
matchesAny(data, attrs) {
return this.whitelist.matchesAny(data, attrs) || this.blacklist.matchesAny(data, attrs);
}
}
/***/ }),
/***/ "./gfp/plugin/autopagerize.js":
/*!************************************!*\
!*** ./gfp/plugin/autopagerize.js ***!
\************************************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
function mutationObserver(mutations, searchGui) {
// all results have finished loading this includes google's own nodes that load later too, such as news items
const res = [];
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType !== 3) {
res.push(addedNode);
}
}
}
if (res.length) {
searchGui.filterResults({
querySelectorAll: selector => {
// - Can't wrap parent/grandparent's `querySelectorAll`, as it will include elements not in `addedNodes`.
// - Can't use node's `querySelectorAll`, as it doesn't include the node itself.
// - Can't create a parent element and move the nodes in it, as the nodes don't get added after the
// MutationObserver.
const matchedNodes = [];
for (const node of res) {
if (node.matches(selector)) {
matchedNodes.push(node);
} // call `querySelectorAll` as well, as `node` can be a results container node
Array.prototype.push.apply(matchedNodes, node.querySelectorAll(selector));
}
return matchedNodes;
}
});
}
}
/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(searchGui, _config) {
const mainNode = document.getElementById('rso');
if (!mainNode || !searchGui) {
return searchGui;
}
new MutationObserver(mutations => mutationObserver(mutations, searchGui)).observe(mainNode, {
subtree: true,
childList: true
});
return searchGui;
}
/***/ }),
/***/ "./gfp/plugin/customsearch.js":
/*!************************************!*\
!*** ./gfp/plugin/customsearch.js ***!
\************************************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../gui */ "./gfp/gui.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ "./gfp/utils.js");
class ResultsData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
*getChildren() {
for (const child of this.node.querySelectorAll('.gsc-table-result')) {
yield new TextData(child);
}
}
}
class TextData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
get linkArea() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'linkArea', this.node.querySelector('.gsc-url-bottom'));
}
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('a.gs-title').href);
}
get title() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'title', this.node.querySelector('a.gs-title').textContent);
}
get summary() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'summary', this.node.querySelector('.gs-snippet').textContent);
}
}
/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(searchGui, config) {
if (window.location.href.indexOf('/cse?') === -1 && window.location.href.indexOf('/custom?') === -1) {
return searchGui;
}
const mainNode = document.getElementById('cse');
if (!mainNode) {
return searchGui;
}
searchGui = new _gui__WEBPACK_IMPORTED_MODULE_0__.SearchGui(ResultsData, config);
new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.classList && addedNode.classList.contains('gcsc-branding')) {
// all results have finished loading
searchGui.nodeData.children.length = 0;
searchGui.filterResults(document.querySelector('.gsc-results'));
}
}
}
}).observe(mainNode, {
subtree: true,
childList: true
});
return searchGui;
}
/***/ }),
/***/ "./gfp/plugin/google.js":
/*!******************************!*\
!*** ./gfp/plugin/google.js ***!
\******************************/
/*! namespace exports */
/*! export ResultsData [provided] [no usage info] [missing usage info prevents renaming] */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ResultsData": () => /* binding */ ResultsData,
/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _gui__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../gui */ "./gfp/gui.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ "./gfp/utils.js");
class ResultsData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
*getChildren() {
for (const child of this.node.querySelectorAll('.g')) {
if (child.classList.contains('obcontainer') || child.classList.contains('kno-kp') || child.classList.contains('g-blk')) {// contains other .g elements, skip so we don't have duplicate links
} else if (child.id === 'imagebox_bigimages') {
yield new ImageContainerData(child);
} else if (child.id === 'lclbox') {
yield new MapContainerData(child);
} else if (child.firstChild.nodeName === 'G-SECTION-WITH-HEADER') {
yield new TweetContainerData(child);
} else if (child.previousElementSibling && child.previousElementSibling.classList.contains('mod')) {
yield new FeaturedSnippetData(child);
} else {
yield new TextData(child);
}
}
for (const child of this.node.querySelectorAll('g-inner-card')) {
yield new NewsData(child);
}
for (const child of this.node.querySelectorAll('div[role="heading"] + div > div > div[data-ved]')) {
yield new VideoData(child);
}
}
}
class CommonData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
get linkArea() {
// query in order of preference
let linkArea = this.node.querySelector('a.fl[href^="https://translate."]') || // "Translate this page"
this.node.querySelector('.action-menu') || // after the action menu
this.node.querySelector('span.b') || // after the bold "PDF" text
this.node.querySelector('cite'); // after the title
if (linkArea) {
linkArea = linkArea.parentNode;
}
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'linkArea', linkArea);
}
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('div[data-ved] > div:first-child > div:first-child > a').href);
}
get title() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'title', this.node.querySelector('h3').textContent);
}
}
class ImageContainerData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
*getChildren() {
for (const child of this.node.querySelectorAll('.bia')) {
yield new ImageData(child);
}
}
}
class ImageData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.href);
}
}
class VideoData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
get linkArea() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'linkArea', this.node.querySelector('span + div > span'));
}
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('a[data-ved]').href);
}
get title() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'title', this.node.querySelector('div[role="heading"]').textContent);
}
}
class MapContainerData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
*getChildren() {
for (const child of this.node.querySelectorAll('div.g')) {
yield new MapData(child);
}
}
}
class MapData extends CommonData {}
class NewsData extends _gui__WEBPACK_IMPORTED_MODULE_0__.NodeData {
get linkArea() {
const query = this.node.querySelector('span[tabindex="-1"] + div > p > span');
if (query == null) {
// drawing hasn't finished
return null;
}
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'linkArea', query.parentNode);
}
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('a').href);
}
get title() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'title', this.node.querySelector('a').textContent);
}
}
class TweetContainerData extends CommonData {
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('g-more-link > a').href);
}
get title() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'title', this.node.querySelector('g-link').textContent);
}
*getChildren() {
for (const child of this.node.querySelectorAll('g-inner-card')) {
yield new TweetSubData(child);
}
}
}
class TweetSubData extends CommonData {
get linkArea() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'linkArea', this.node.querySelector('span.f'));
}
get title() {
return '';
}
get url() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'url', this.node.querySelector('a').href);
}
get summary() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'summary', this.node.querySelector('a').textContent);
}
}
class FeaturedSnippetData extends CommonData {
get summary() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'summary', this.node.previousElementSibling.textContent);
}
}
class TextData extends CommonData {
get summary() {
return (0,_utils__WEBPACK_IMPORTED_MODULE_1__.cache)(this, 'summary', this.node.querySelector('div[data-ved] > div:first-child > div:nth-child(2)').textContent);
}
}
/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(searchGui, config) {
if (window.location.href.indexOf('/search?') === -1) {
return;
}
searchGui = new _gui__WEBPACK_IMPORTED_MODULE_0__.SearchGui(ResultsData, config);
searchGui.filterResults(document.getElementById('search'));
return searchGui;
}
/***/ }),
/***/ "./gfp/plugin/instant.js":
/*!*******************************!*\
!*** ./gfp/plugin/instant.js ***!
\*******************************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(searchGui, _config) {
const mainNode = document.getElementById('main');
if (!mainNode || !searchGui) {
return searchGui;
}
new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
const node = addedNode.querySelector && addedNode.querySelector(':scope > #ires');
if (node) {
// all results have finished loading
searchGui.nodeData.children.length = 0;
searchGui.filterResults(node);
}
}
}
}).observe(mainNode, {
subtree: true,
childList: true
});
return searchGui;
}
/***/ }),
/***/ "./gfp/pref.js":
/*!*********************!*\
!*** ./gfp/pref.js ***!
\*********************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.n, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => /* binding */ Pref
/* harmony export */ });
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var slickgrid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! slickgrid */ "slickgrid");
/* harmony import */ var slickgrid__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(slickgrid__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _html_pref_html__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./html/pref.html */ "./gfp/html/pref.html");
/* harmony import */ var _html_pref_html__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_html_pref_html__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _css_pref_sass__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./css/pref.sass */ "./gfp/css/pref.sass");
/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./filter */ "./gfp/filter.js");
/* harmony import */ var _lib_filterClasses__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./lib/filterClasses */ "./gfp/lib/filterClasses.js");
/* harmony import */ var _matcher__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./matcher */ "./gfp/matcher.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./utils */ "./gfp/utils.js");
class Pref {
constructor(searchGui) {
this.searchGui = searchGui;
this.dialog = null;
this.resourcesAdded = false;
GM_registerMenuCommand('Google Search Filter +', this.openDialog.bind(this), null);
}
openDialog() {
if (this.dialog) {
return;
}
this.addResources();
this.dialog = new PrefDialog(this.searchGui).dialog.on('dialogclose', () => this.dialog = null);
}
addResources() {
if (this.resourcesAdded) {
return;
}
(0,_utils__WEBPACK_IMPORTED_MODULE_7__.addStyleResolve)('jquery-ui-css');
(0,_utils__WEBPACK_IMPORTED_MODULE_7__.addStyleResolve)('slickgrid-css');
GM_addStyle(_css_pref_sass__WEBPACK_IMPORTED_MODULE_3__.default.toString());
this.resourcesAdded = true;
}
}
class DataView {
/**
Supports filtering & sorting.
config.filters is used as the actual data source.
*/
constructor(grid, comparer, filterer, searchGui) {
this.grid = grid;
this.comparer = comparer;
this.filterer = filterer;
this.searchGui = searchGui;
this.config = searchGui.config;
this.filters = [];
this._filterObserver = this.filterObserver.bind(this);
this.config.filters.observe(this._filterObserver);
}
destructor() {
this.config.filters.unobserve(this._filterObserver);
}
static filterToitem(filter) {
return {
text: filter.text,
slow: _matcher__WEBPACK_IMPORTED_MODULE_6__.CombinedMultiMatcher.isSlowFilter(filter),
enabled: !filter.disabled,
hitCount: filter.hitCount,
lastHit: filter.lastHit
};
}
static itemToFilter(item) {
return _filter__WEBPACK_IMPORTED_MODULE_4__.Filter.fromObject(item.text, {
disabled: !item.enabled,
hitCount: item.hitCount,
lastHit: item.lastHit
});
}
_render(resetSelection, resetRows, resetRowCount) {
if (resetSelection) {
this.grid.resetActiveCell();
this.grid.setSelectedRows([]);
}
if (resetRows) {
this.grid.invalidateAllRows();
}
if (resetRowCount) {
this.grid.updateRowCount();
}
this.grid.render();
}
getLength() {
return this.filters.length;
}
_editOp(call, func) {
/**
args:
call: whether the action comes from pref
*/
if (this._enterLock) {
return;
}
this._enterLock = true;
func();
if (call) {
this.config.flushFilters();
this.searchGui.filterResults();
}
this._enterLock = false;
}
add(filter, call = true) {
this._editOp(call, () => {
if (call) {
this.config.filters.add(filter);
} else if (!this.filterer(filter)) {
return;
}
const i = (0,_utils__WEBPACK_IMPORTED_MODULE_7__.bisect)(this.filters, filter, this.comparer);
this.filters.splice(i, 0, filter);
this._render(true, true, true);
if (call) {
this.grid.scrollRowIntoView(i);
}
});
}
remove(filters, is, call = true) {
this._editOp(call, () => {
if (call) {
this.config.filters.remove(is.map(i => this.filters[i]));
} else {
// use unique comparer for speed
const comparer = (x, y) => x['text'] > y['text'] ? 1 : x['text'] < y['text'] ? -1 : 0;
is = (0,_utils__WEBPACK_IMPORTED_MODULE_7__.indexOfSorted)(this.filters.sort(comparer), filters.sort(comparer), comparer);
this.filters.sort(this.comparer);
}
(0,_utils__WEBPACK_IMPORTED_MODULE_7__.popMany)(this.filters, is);
this._render(true, true, true);
});
}
addTemp(i) {
this.filters.splice(i, 0, _filter__WEBPACK_IMPORTED_MODULE_4__.Filter.fromText(''));
this._render(true, true, true);
}
removeTemp(i) {
this.filters.splice(i, 1);
this._render(true, true, true);
}
update(filter, i, call = true) {
this._editOp(call, () => {
if (call) {
// remove & add since matcher doesn't support updates
this.config.filters.remove([this.filters[i]]);
this.config.filters.add(filter);
} else {
i = this.filters.indexOf(filter);
if (i === -1) {
return;
}
}
this.filters.splice(i, 1);
i = (0,_utils__WEBPACK_IMPORTED_MODULE_7__.bisect)(this.filters, filter, this.comparer);
this.filters.splice(i, 0, filter);
this._render(false, true, false);
if (call) {
this.grid.scrollRowIntoView(i);
}
});
}
getValue() {
return this.config.filters;
}
setValue(filters = null, call = true) {
this._editOp(call, () => {
if (filters === null) {
filters = Array.from(this.config.filters);
} else if (call) {
this.config.filters.setValue(filters);
}
this.filters = filters.filter(this.filterer).sort(this.comparer);
this._render(true, true, true);
});
}
getItem(i) {
return this.constructor.filterToitem(this.filters[i]);
}
sort() {
this.filters.sort(this.comparer);
this._render(true, true, false);
}
filter() {
this.filters = Array.from(this.config.filters).filter(this.filterer).sort(this.comparer);
this._render(true, true, true);
}
filterObserver(type, value) {
switch (type) {
case 'add':
this.add(value, false);
break;
case 'remove':
this.remove([value], null, false);
break;
case 'update':
this.update(value, null, false);
break;
case 'setValue':
this.setValue(value, false);
break;
}
}
}
class PrefDialog {
constructor(searchGui) {
this.searchGui = searchGui;
this.dialog = jquery__WEBPACK_IMPORTED_MODULE_0___default()((_html_pref_html__WEBPACK_IMPORTED_MODULE_2___default())).dialog(Object.assign(this.dialogConfig, {
title: 'Google Search Filter +',
closeOnEscape: false,
close: this.destructor.bind(this)
}));
this.dataView = null;
this.addImportExport();
this.addGrid();
}
destructor() {
this.dataView.destructor();
this.dialog.remove();
}
get dialogConfig() {
return {
width: jquery__WEBPACK_IMPORTED_MODULE_0___default()(window).width() * 0.5,
height: jquery__WEBPACK_IMPORTED_MODULE_0___default()(window).height() * 0.5,
close() {
jquery__WEBPACK_IMPORTED_MODULE_0___default()(this).remove();
}
};
}
addImportExport() {
const self = this;
this.dialog.find('.import').click(_e => {
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<textarea></textarea>').dialog(Object.assign(this.dialogConfig, {
title: 'Import',
buttons: [{
text: 'OK',
click() {
const filtersObject = JSON.parse(jquery__WEBPACK_IMPORTED_MODULE_0___default()(this).val());
const filters = [];
for (const key in filtersObject) {
if (Object.prototype.hasOwnProperty.call(filtersObject, key)) {
filters.push(_filter__WEBPACK_IMPORTED_MODULE_4__.Filter.fromObject(key, filtersObject[key]));
}
}
self.dataView.setValue(filters);
jquery__WEBPACK_IMPORTED_MODULE_0___default()(this).dialog('close');
}
}, {
text: 'Cancel',
click() {
jquery__WEBPACK_IMPORTED_MODULE_0___default()(this).dialog('close');
}
}],
create() {
setTimeout(() => this.select(), 0);
}
}));
return false;
});
this.dialog.find('.export').click(_e => {
const filtersObject = {};
for (const filter of this.dataView.getValue()) {
filtersObject[filter.text] = filter.toObject();
}
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<textarea></textarea>').attr('readonly', 'readonly').val(JSON.stringify(filtersObject, null, 2)).dialog(Object.assign(this.dialogConfig, {
title: 'Export',
buttons: [{
text: 'Close',
click() {
jquery__WEBPACK_IMPORTED_MODULE_0___default()(this).dialog('close');
}
}],
create() {
setTimeout(() => {
this.focus();
this.setSelectionRange(0, this.value.length, 'backward');
}, 0);
}
}));
return false;
});
}
addGrid() {
const gridDom = this.dialog.find('.grid');
this.dataView = new DataView(null, null, null, this.searchGui);
const grid = new (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().Grid)(gridDom, this.dataView, [{
id: 'text',
field: 'text',
name: 'Filter Rule',
width: 300,
sortable: true,
formatter: (row, cell, value, _columnDef, _dataContext) => `<span class="${value.startsWith('@@') ? 'whitelist' : 'blocking'}-filter">${value}</span>`,
editor: (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().Editors.Text),
validator: text => {
// spaces only don't count as being empty, since they can exist in urls
if (!text) return {
valid: false,
msg: 'Empty filter'
};
if (_filter__WEBPACK_IMPORTED_MODULE_4__.Filter.fromText(text) instanceof _lib_filterClasses__WEBPACK_IMPORTED_MODULE_5__.InvalidFilter) return {
valid: false,
msg: 'Invalid filter'
};
if (Array.from(this.dataView.getValue()).some(filter => filter.text === text)) {
return {
valid: false,
msg: 'Duplicate filter'
};
}
return {
valid: true,
msg: null
};
}
}, {
// use css for the image since there can be many slow filters
id: 'slow',
field: 'slow',
name: '!',
width: 1,
sortable: true,
cssClass: 'slow-column',
formatter: (row, cell, value, _columnDef, _dataContext) => value ? '<img class="slow-image" />' : ''
}, {
id: 'enabled',
field: 'enabled',
name: 'Enabled',
width: 45,
sortable: true,
formatter: (row, cell, value, _columnDef, _dataContext) => `<input type="checkbox" name="" value="${value}" checked=${!!value} />`
}, {
id: 'hitCount',
field: 'hitCount',
name: 'Hits',
width: 1,
sortable: true,
editor: (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().Editors.Integer),
validator: val => val < 0 ? {
valid: false,
msg: 'Must be >= 0'
} : {
valid: true,
msg: null
}
}, {
id: 'lastHit',
field: 'lastHit',
name: 'Last Hit',
width: 110,
sortable: true,
formatter: (row, cell, value, columnDef, dataContext) => {
if (!value || dataContext.hitCount === 0) {
return '';
}
const date = new Date(value);
return `${date.getFullYear()}-${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getMonth() + 1, 2)}-${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getDate(), 2)} ` + `${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getHours(), 2)}:${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getMinutes(), 2)}:${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getSeconds(), 2)}:` + `${(0,_utils__WEBPACK_IMPORTED_MODULE_7__.pad)(date.getMilliseconds(), 3)}`;
},
editor: (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().Editors.Integer)
}], {
autoEdit: false,
editable: true,
enableCellNavigation: true,
enableColumnReorder: false,
explicitInitialization: true,
forceFitColumns: true,
showHeaderRow: true
});
/* Find bar */
let filterVals = {};
const binaryFilter = ['FfNn-', 'TtYy+'];
window.grid = grid;
const dateFormatter = grid.getColumns()[grid.getColumnIndex('lastHit')].formatter;
this.dataView.filterer = val => {
val = DataView.filterToitem(val);
for (const key in filterVals) {
switch (key) {
case 'text':
if (!val[key].includes(filterVals[key])) {
return false;
}
break;
case 'slow':
case 'enabled':
if (!binaryFilter[+val[key]].includes(filterVals[key])) {
return false;
}
break;
case 'hitCount':
if (!val[key].toString().includes(filterVals[key])) {
return false;
}
break;
case 'lastHit':
if (!dateFormatter(null, null, val[key], null, val).includes(filterVals[key])) {
return false;
}
break;
}
}
return true;
};
const findBar = gridDom.find('.slick-headerrow');
const openFindBar = () => findBar.show().find('input:first').focus();
const closeFindBar = () => {
findBar.hide().find('input').val('');
filterVals = {};
this.dataView.filter();
this.dialog.focus();
};
grid.onHeaderRowCellRendered.subscribe((e, args) => {
const searchField = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<input/>').keydown(e => {
if (e.keyCode === 27) {
closeFindBar();
}
}).on('input', _e => {
filterVals[args.column.field] = searchField.val();
this.dataView.filter();
});
jquery__WEBPACK_IMPORTED_MODULE_0___default()(args.node).empty().append(searchField);
});
findBar.hide();
this.dialog.attr('tabindex', 1);
this.dialog.keydown(e => {
if ((e.ctrlKey || e.metaKey) && e.keyCode === 70) {
openFindBar();
e.preventDefault();
}
});
/* Sorting */
let [sortField, sortRes] = ['text', 1];
this.dataView.comparer = (x, y) => x[sortField] > y[sortField] ? sortRes : x[sortField] < y[sortField] ? -sortRes : 0;
grid.setSortColumn(sortField, !!sortRes);
grid.onSort.subscribe((e, args) => {
;
[sortField, sortRes] = [args.sortCol.field, args.sortAsc ? 1 : -1];
this.dataView.sort();
});
/* Editing */
grid.onClick.subscribe((e, args) => {
if (jquery__WEBPACK_IMPORTED_MODULE_0___default()(e.target).is(':checkbox')) {
const column = grid.getColumns()[args.cell];
if (column.editable === false || column.autoEdit === false) {
return;
}
const item = this.dataView.getItem(args.row);
item[column.field] = !item[column.field];
new grid.onCellChange.notify({
row: args.row,
cell: args.cell,
item: item
}, new (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().EventData)());
}
});
grid.onValidationError.subscribe((e, args) => alert(args.validationResults.msg));
grid.onCellChange.subscribe((e, args) => this.dataView.update(DataView.itemToFilter(args.item), args.row));
gridDom.on('blur', 'input.editor-text', () => slickgrid__WEBPACK_IMPORTED_MODULE_1___default().GlobalEditorLock.commitCurrentEdit());
grid.setSelectionModel(new (slickgrid__WEBPACK_IMPORTED_MODULE_1___default().RowSelectionModel)());
/* Add & Remove */
let cancelled = true;
let tempI = null;
grid.onCellChange.subscribe((_e, _args) => cancelled = false);
grid.onBeforeCellEditorDestroy.subscribe((_e, _args) => {
if (cancelled && tempI !== null) {
setTimeout(() => {
this.dataView.removeTemp(tempI);
tempI = null;
}, 0);
}
cancelled = true;
});
const addFilter = () => {
const is = grid.getSelectedRows();
tempI = is[is.length - 1] || 0;
this.dataView.addTemp(tempI);
grid.gotoCell(tempI, 0, true);
};
const removeFilter = () => this.dataView.remove(null, grid.getSelectedRows());
this.dialog.find('.add').click(_e => {
addFilter();
return false;
});
gridDom.keydown(e => {
if (e.target.nodeName === 'INPUT') {
return;
}
switch (e.keyCode) {
case 45:
addFilter();
break;
case 46:
removeFilter();
break;
case 65:
if (e.ctrlKey || e.metaKey) {
const rows = [];
for (let i = 0; i < grid.getDataLength(); i++) {
rows.push(i);
}
grid.setSelectedRows(rows);
e.preventDefault();
}
break;
}
});
/* Initialize grid & dataView */
grid.init();
this.dataView.grid = grid;
this.dataView.setValue();
/* Dialog */
const height = gridDom.height();
this.dialog.on('dialogresize', (e, ui) => {
gridDom.css('height', `${height + (ui.size.height - ui.originalSize.height)}px`);
grid.resizeCanvas();
});
}
}
/***/ }),
/***/ "./gfp/utils.js":
/*!**********************!*\
!*** ./gfp/utils.js ***!
\**********************/
/*! namespace exports */
/*! export addStyleResolve [provided] [no usage info] [missing usage info prevents renaming] */
/*! export bisect [provided] [no usage info] [missing usage info prevents renaming] */
/*! export cache [provided] [no usage info] [missing usage info prevents renaming] */
/*! export indexOfSorted [provided] [no usage info] [missing usage info prevents renaming] */
/*! export pad [provided] [no usage info] [missing usage info prevents renaming] */
/*! export popMany [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "addStyleResolve": () => /* binding */ addStyleResolve,
/* harmony export */ "pad": () => /* binding */ pad,
/* harmony export */ "cache": () => /* binding */ cache,
/* harmony export */ "bisect": () => /* binding */ bisect,
/* harmony export */ "indexOfSorted": () => /* binding */ indexOfSorted,
/* harmony export */ "popMany": () => /* binding */ popMany
/* harmony export */ });
function addStyleResolve(name) {
GM_addStyle(GM_getResourceText(name).replace(/url\("?([^":]+)"?\)/g, (match, url) => `url("${GM_getResourceURL(`${name}/${url}`)}")`));
}
function pad(num, size) {
return Array(Math.max(size - num.toString().length + 1, 0)).join(0) + num;
}
function cache(obj, prop, value) {
Object.defineProperty(obj, prop, {
value: value
});
return value;
}
function bisect(a, x, comparer, lo = 0, hi = null) {
// ported from the python standard library
if (lo < 0) {
throw 'lo must be non-negative';
}
if (hi === null) {
hi = a.length;
}
while (lo < hi) {
const mid = lo + hi >> 1;
if (comparer(x, a[mid]) < 0) {
hi = mid;
} else {
lo = mid + 1;
}
}
return lo;
}
function indexOfSorted(xs, ys, comparer) {
const res = [];
let i = 0;
for (const y of ys) {
// noinspection JSSuspiciousNameCombination
i = bisect(xs, y, comparer, i + 1) - 1;
res.push(xs[i] === y ? i : -1);
}
return res;
}
function popMany(xs, is) {
// O(n) time, mask is not'ed for speed
const mask = new Array(xs.length);
for (const i of is) {
mask[i] = true;
}
let offset = 0;
for (let i = 0; i < xs.length; i++) {
if (mask[i] === undefined) {
xs[offset] = xs[i];
offset++;
}
}
xs.length = offset;
return xs;
}
/***/ }),
/***/ "./node_modules/css-loader/dist/runtime/api.js":
/*!*****************************************************!*\
!*** ./node_modules/css-loader/dist/runtime/api.js ***!
\*****************************************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
"use strict";
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
// eslint-disable-next-line func-names
module.exports = function (cssWithMappingToString) {
var list = []; // return the list of modules as css string
list.toString = function toString() {
return this.map(function (item) {
var content = cssWithMappingToString(item);
if (item[2]) {
return "@media ".concat(item[2], " {").concat(content, "}");
}
return content;
}).join('');
}; // import a list of modules into the list
// eslint-disable-next-line func-names
list.i = function (modules, mediaQuery, dedupe) {
if (typeof modules === 'string') {
// eslint-disable-next-line no-param-reassign
modules = [[null, modules, '']];
}
var alreadyImportedModules = {};
if (dedupe) {
for (var i = 0; i < this.length; i++) {
// eslint-disable-next-line prefer-destructuring
var id = this[i][0];
if (id != null) {
alreadyImportedModules[id] = true;
}
}
}
for (var _i = 0; _i < modules.length; _i++) {
var item = [].concat(modules[_i]);
if (dedupe && alreadyImportedModules[item[0]]) {
// eslint-disable-next-line no-continue
continue;
}
if (mediaQuery) {
if (!item[2]) {
item[2] = mediaQuery;
} else {
item[2] = "".concat(mediaQuery, " and ").concat(item[2]);
}
}
list.push(item);
}
};
return list;
};
/***/ }),
/***/ "./node_modules/css-loader/dist/runtime/getUrl.js":
/*!********************************************************!*\
!*** ./node_modules/css-loader/dist/runtime/getUrl.js ***!
\********************************************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
"use strict";
module.exports = function (url, options) {
if (!options) {
// eslint-disable-next-line no-param-reassign
options = {};
} // eslint-disable-next-line no-underscore-dangle, no-param-reassign
url = url && url.__esModule ? url.default : url;
if (typeof url !== 'string') {
return url;
} // If url is already wrapped in quotes, remove them
if (/^['"].*['"]$/.test(url)) {
// eslint-disable-next-line no-param-reassign
url = url.slice(1, -1);
}
if (options.hash) {
// eslint-disable-next-line no-param-reassign
url += options.hash;
} // Should url be wrapped?
// See https://drafts.csswg.org/css-values-3/#urls
if (/["'() \t\n]/.test(url) || options.needQuotes) {
return "\"".concat(url.replace(/"/g, '\\"').replace(/\n/g, '\\n'), "\"");
}
return url;
};
/***/ }),
/***/ "./node_modules/html-loader/dist/runtime/getUrl.js":
/*!*********************************************************!*\
!*** ./node_modules/html-loader/dist/runtime/getUrl.js ***!
\*********************************************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
"use strict";
module.exports = function (url, options) {
if (!options) {
// eslint-disable-next-line no-param-reassign
options = {};
} // eslint-disable-next-line no-underscore-dangle, no-param-reassign
url = url && url.__esModule ? url.default : url;
if (typeof url !== 'string') {
return url;
}
if (options.hash) {
// eslint-disable-next-line no-param-reassign
url += options.hash;
}
if (options.maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) {
return "\"".concat(url, "\"");
}
return url;
};
/***/ }),
/***/ "./gfp/css/gui.sass":
/*!**************************!*\
!*** ./gfp/css/gui.sass ***!
\**************************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.n, __webpack_exports__, __webpack_require__.r, module.id, __webpack_require__.d, __webpack_require__.*, module */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]});
// Module
___CSS_LOADER_EXPORT___.push([module.id, ".hide {\n display: none !important;\n}\n\n.filter-add {\n margin-left: 5px;\n font-size: 14px;\n text-decoration: none;\n}\n.filter-add:hover {\n text-decoration: underline;\n}\n\ncite + .filter-add {\n margin-left: 10px;\n}\n\n.show-title {\n padding-right: 5px;\n color: #999;\n}\n\n.show-link {\n color: #999 !important;\n text-decoration: none;\n}\n.show-link.hide {\n display: inline !important;\n color: #12C !important;\n}\n\n.gs-webResult div.gs-visibleUrl-long {\n display: inline;\n}", ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./gfp/css/pref.sass":
/*!***************************!*\
!*** ./gfp/css/pref.sass ***!
\***************************/
/*! namespace exports */
/*! export default [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.n, __webpack_exports__, __webpack_require__.r, module.id, __webpack_require__.d, __webpack_require__.*, module */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/getUrl.js */ "./node_modules/css-loader/dist/runtime/getUrl.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _img_slow_png__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../img/slow.png */ "./gfp/img/slow.png");
/* harmony import */ var _img_slow_png__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_img_slow_png__WEBPACK_IMPORTED_MODULE_2__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]});
var ___CSS_LOADER_URL_REPLACEMENT_0___ = _node_modules_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_1___default()((_img_slow_png__WEBPACK_IMPORTED_MODULE_2___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, ".ui-front {\n z-index: 1000;\n}\n\n.ui-dialog textarea {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n width: 100% !important;\n resize: none;\n}\n\n.gfp {\n outline: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n display: -webkit-box !important;\n display: -ms-flexbox !important;\n display: flex !important;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n}\n.gfp .slick-sort-indicator {\n float: none;\n}\n.gfp a {\n outline: 0;\n}\n.gfp .button-icon {\n height: 16px;\n width: 16px;\n}\n.gfp .row:last-child {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n}\n.gfp .slow-column {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n}\n.gfp .slick-cell:first-child {\n white-space: pre;\n}\n.gfp .slick-cell .whitelist-filter {\n color: #080;\n}\n.gfp .slick-cell .slow-image {\n content: url(" + ___CSS_LOADER_URL_REPLACEMENT_0___ + ");\n}\n.gfp .slick-cell.selected {\n background: #f5f5f5;\n}\n.gfp .slick-header-column:nth-child(2) > .slick-column-name {\n display: table;\n margin: 0 auto;\n}\n.gfp .slick-headerrow-column {\n background: #E6E6E6;\n height: 25px;\n padding: 0;\n border: 0;\n}\n.gfp .slick-cell input, .gfp .slick-headerrow-column input {\n margin: 0;\n padding: 0;\n width: 100%;\n height: 100%;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}", ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./gfp/html/pref.html":
/*!****************************!*\
!*** ./gfp/html/pref.html ***!
\****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
// Imports
var ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___ = __webpack_require__(/*! ../../node_modules/html-loader/dist/runtime/getUrl.js */ "./node_modules/html-loader/dist/runtime/getUrl.js");
var ___HTML_LOADER_IMPORT_0___ = __webpack_require__(/*! ../img/edit_add.png */ "./gfp/img/edit_add.png");
var ___HTML_LOADER_IMPORT_1___ = __webpack_require__(/*! ../img/import.png */ "./gfp/img/import.png");
var ___HTML_LOADER_IMPORT_2___ = __webpack_require__(/*! ../img/export.png */ "./gfp/img/export.png");
// Module
var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
var ___HTML_LOADER_REPLACEMENT_1___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_1___);
var ___HTML_LOADER_REPLACEMENT_2___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_2___);
var code = "<div class=\"gfp\"> <div class=\"row\"> <a href=\"#\" class=\"add\" title=\"Add filter\"><img class=\"button-icon\" src=\"" + ___HTML_LOADER_REPLACEMENT_0___ + "\"/></a> <a href=\"#\" class=\"import\" title=\"Import filters\"><img class=\"button-icon\" src=\"" + ___HTML_LOADER_REPLACEMENT_1___ + "\"/></a> <a href=\"#\" class=\"export\" title=\"Export filters\"><img class=\"button-icon\" src=\"" + ___HTML_LOADER_REPLACEMENT_2___ + "\"/></a> </div> <div class=\"row\"> <div class=\"grid\"></div> </div> </div> ";
// Exports
module.exports = code;
/***/ }),
/***/ "./gfp/img/edit_add.png":
/*!******************************!*\
!*** ./gfp/img/edit_add.png ***!
\******************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
module.exports = "data:img/png;base64,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"
/***/ }),
/***/ "./gfp/img/export.png":
/*!****************************!*\
!*** ./gfp/img/export.png ***!
\****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
module.exports = "data:img/png;base64,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"
/***/ }),
/***/ "./gfp/img/import.png":
/*!****************************!*\
!*** ./gfp/img/import.png ***!
\****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
module.exports = "data:img/png;base64,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"
/***/ }),
/***/ "./gfp/img/slow.png":
/*!**************************!*\
!*** ./gfp/img/slow.png ***!
\**************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/***/ ((module) => {
module.exports = "data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAQCAMAAAA/D5+aAAABWVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACheQDX19c8LgCIZgCVlZUaGhoiIiJuUwBYWFh/XwByVgBmTQAuLi6WcQAqKiodHR3Jyck0JwBtUgCLaAAgGAAyJgBUQACCgoK4uLhzVgAaEwB3WgBYQgAqHwAeHh4jIyNkZGR1WABAMAC/v78pHwCEYwBMOQBOOgB5WwCFZACWlpaSbgCDYgATExNHR0cFBQUwJQCGZQCIZwBRPQAMCQCXl5c7LAAWFhaFhYUhISFhYWE2NjZDMwAHBweSkpJ6XABLS0sVFRUKCABISEhrUQBJNwAdFgBOOwCYmJgUFBQA9R6HAAAAKHRSTlMAgpRMfYSBS36Zut28HF0Ua2ppmyWcOpGKPGXCYaHhibauhm11LYAjiwhFZAAAAPxJREFUeF5lzVVTAzEYRuEUaFF3dzlf6oq7u7u76/8XkixDLzgXO/Puk0yUVy6uAjfyMR9yPCmEVDIZgxJnVJmzpU6qWRZXiGZLRagWnJSRkN928Rmqo7y43hEpke2Vzztre+40PiqsVCLyyMvbB0Fj3+Z5H/EBagzlGeLCvTQsslirYFVrAoZ6kOkZsWUQScPgkDbU4N3KEBMZGZWx8Qkmp7Tpi0ZDTYjMEpwjJPMshC0sRWhVpjbWRNY3NrfknR1tC9NuoWM/og8OjxLHJ6dnnGsXncoGl1d2wfWN9rpF/dbFfVxne0gbydYdf4LnKECUV/W/Xn+gz9//Bz+04TZYU20HQAAAAABJRU5ErkJggg=="
/***/ }),
/***/ "jquery":
/*!********************!*\
!*** external "$" ***!
\********************/
/*! dynamic exports */
/*! export __esModule [maybe provided (runtime-defined)] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [maybe provided (runtime-defined)] [no usage info] */
/*! runtime requirements: module */
/***/ ((module) => {
"use strict";
module.exports = $;
/***/ }),
/***/ "slickgrid":
/*!************************!*\
!*** external "Slick" ***!
\************************/
/*! dynamic exports */
/*! export __esModule [maybe provided (runtime-defined)] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [maybe provided (runtime-defined)] [no usage info] */
/*! runtime requirements: module */
/***/ ((module) => {
"use strict";
module.exports = Slick;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => module['default'] :
/******/ () => module;
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/ // startup
/******/ // Load entry module
/******/ __webpack_require__("./gfp/bin/main.js");
/******/ // This entry module used 'exports' so it can't be inlined
/******/ })()
;
@Korb
Copy link

Korb commented Apr 27, 2021

Mozilla Firefox 89.0b4 (64-bit), Tampermonkey 4.12.6132 (19 March 2021), Microsoft Windows 10.0.19042.928 — the installed script had no effect on the google search results page.

@simonzack
Copy link
Author

I've updated the repo to fix text data. Google changes it's dom sometimes.

@Korb
Copy link

Korb commented May 4, 2021

I've updated the repo to fix text data. Google changes it's dom sometimes.

I still don't see any difference in the Google search results page with script enabled and disabled. What exactly should they be, and what do they include? Mozilla Firefox 89.0b7 (64-bit), Tampermonkey 4.13.6136 (1 May 2021).

@simonzack
Copy link
Author

I've updated the script now, try the updated version.

@Korb
Copy link

Korb commented Jun 1, 2021

Only language selection?

2021-06-01_21-49-06

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment