Add url params clean

This commit is contained in:
the1812 2019-12-19 21:21:46 +08:00
parent 7eeae629d8
commit 01e461ec52
13 changed files with 240 additions and 183 deletions

View File

@ -33,7 +33,7 @@ declare global {
ontimeout?: (response: MonkeyXhrResponse) => void ontimeout?: (response: MonkeyXhrResponse) => void
onload?: (response: MonkeyXhrResponse) => void onload?: (response: MonkeyXhrResponse) => void
} }
type RunAtOptions = "document-start" | "document-end" | "document-idle" | "document-body" | "context-menu"; type RunAtOptions = "document-start" | "document-end" | "document-idle" | "document-body" | "context-menu"
type DanmakuOption = '无' | 'XML' | 'ASS' type DanmakuOption = '无' | 'XML' | 'ASS'
type DashCodec = 'AVC/H.264' | 'HEVC/H.265' type DashCodec = 'AVC/H.264' | 'HEVC/H.265'
type Pattern = string type Pattern = string
@ -65,77 +65,77 @@ declare global {
} }
interface MonkeyInfo { interface MonkeyInfo {
script: { script: {
author: string; author: string
copyright: string; copyright: string
description: string; description: string
excludes: string[]; excludes: string[]
homepage: string; homepage: string
icon: string; icon: string
icon64: string; icon64: string
includes: string[]; includes: string[]
lastUpdated: number; lastUpdated: number
matches: string[]; matches: string[]
downloadMode: string; downloadMode: string
name: string; name: string
namespace: string; namespace: string
options: { options: {
awareOfChrome: boolean; awareOfChrome: boolean
compat_arrayleft: boolean; compat_arrayleft: boolean
compat_foreach: boolean; compat_foreach: boolean
compat_forvarin: boolean; compat_forvarin: boolean
compat_metadata: boolean; compat_metadata: boolean
compat_prototypes: boolean; compat_prototypes: boolean
compat_uW_gmonkey: boolean; compat_uW_gmonkey: boolean
noframes: boolean; noframes: boolean
override: { override: {
excludes: false; excludes: false
includes: false; includes: false
orig_excludes: string[]; orig_excludes: string[]
orig_includes: string[]; orig_includes: string[]
use_excludes: string[]; use_excludes: string[]
use_includes: string[]; use_includes: string[]
};
run_at: RunAtOptions;
};
position: number;
resources: string[];
"run-at": RunAtOptions;
system: boolean;
unwrap: boolean;
version: string;
} }
scriptMetaStr: string; run_at: RunAtOptions
scriptSource: string; }
scriptUpdateURL: string; position: number
scriptWillUpdate: boolean; resources: string[]
scriptHandler: string; "run-at": RunAtOptions
isIncognito: boolean; system: boolean
version: string; unwrap: boolean
version: string
}
scriptMetaStr: string
scriptSource: string
scriptUpdateURL: string
scriptWillUpdate: boolean
scriptHandler: string
isIncognito: boolean
version: string
} }
interface CustomNavbarComponents { interface CustomNavbarComponents {
blank1: number; blank1: number
logo: number; logo: number
category: number; category: number
rankingLink: number; rankingLink: number
drawingLink: number; drawingLink: number
musicLink: number; musicLink: number
gamesIframe: number; gamesIframe: number
livesIframe: number; livesIframe: number
shopLink: number; shopLink: number
mangaLink: number; mangaLink: number
blank2: number; blank2: number
search: number; search: number
userInfo: number; userInfo: number
messages: number; messages: number
activities: number; activities: number
bangumi: number; bangumi: number
watchlaterList: number; watchlaterList: number
favoritesList: number; favoritesList: number
historyList: number; historyList: number
upload: number; upload: number
blank3: number; blank3: number
} }
type CustomNavbarOrders = { [key in keyof CustomNavbarComponents]: number }; type CustomNavbarOrders = { [key in keyof CustomNavbarComponents]: number }
interface SimpleHomeCategoryOrders { interface SimpleHomeCategoryOrders {
anime: number anime: number
bangumi: number bangumi: number
@ -158,7 +158,7 @@ declare global {
documentary: number documentary: number
[key: string]: number [key: string]: number
} }
const unsafeWindow: Window; const unsafeWindow: Window
const UserAgent: string const UserAgent: string
const EmptyImageUrl: string const EmptyImageUrl: string
interface Window { interface Window {
@ -169,99 +169,99 @@ declare global {
[key: string]: any [key: string]: any
} }
class SpinQuery { class SpinQuery {
static condition<T>(query: () => T, condition: (queryResult: T) => boolean, success: (queryResult: T) => void, failed?: () => void): void; static condition<T>(query: () => T, condition: (queryResult: T) => boolean, success: (queryResult: T) => void, failed?: () => void): void
static condition<T>(query: () => T, condition: (queryResult: T) => boolean): Promise<T>; static condition<T>(query: () => T, condition: (queryResult: T) => boolean): Promise<T>
static select<T>(query: () => T, action: (queryResult: T) => void, failed?: () => void): void; static select<T>(query: () => T, action: (queryResult: T) => void, failed?: () => void): void
static select<T>(query: () => T): Promise<T>; static select<T>(query: () => T): Promise<T>
static select(query: string): Promise<HTMLElement | null>; static select(query: string): Promise<HTMLElement | null>
static select(query: string, action: (queryResult: HTMLElement) => void, failed?: () => void): void; static select(query: string, action: (queryResult: HTMLElement) => void, failed?: () => void): void
static any<T>(query: () => T, action: (queryResult: T) => void, failed?: () => void): void; static any<T>(query: () => T, action: (queryResult: T) => void, failed?: () => void): void
static any<T>(query: () => T): Promise<T>; static any<T>(query: () => T): Promise<T>
static any(query: string): Promise<JQuery>; static any(query: string): Promise<JQuery>
static any(query: string, action: (queryResult: JQuery) => void, failed?: () => void): void; static any(query: string, action: (queryResult: JQuery) => void, failed?: () => void): void
static count<T>(query: () => T, count: number, success: (queryResult: T) => void, failed?: () => void): void; static count<T>(query: () => T, count: number, success: (queryResult: T) => void, failed?: () => void): void
static count<T>(query: () => T, count: number): Promise<T>; static count<T>(query: () => T, count: number): Promise<T>
static count(query: string, count: number): Promise<NodeListOf<Element>>; static count(query: string, count: number): Promise<NodeListOf<Element>>
static count(query: string, count: number, success: (queryResult: NodeListOf<Element>) => void, failed?: () => void): Promise<void>; static count(query: string, count: number, success: (queryResult: NodeListOf<Element>) => void, failed?: () => void): Promise<void>
static unsafeJquery(action: () => void, failed?: () => void): void; static unsafeJquery(action: () => void, failed?: () => void): void
static unsafeJquery(): Promise<void>; static unsafeJquery(): Promise<void>
} }
class Toast { class Toast {
show(): void; show(): void
dismiss(): void; dismiss(): void
element: HTMLElement; element: HTMLElement
key: string; key: string
static show(message: string, title: string, duration?: number): Toast; static show(message: string, title: string, duration?: number): Toast
static info(message: string, title: string, duration?: number): Toast; static info(message: string, title: string, duration?: number): Toast
static success(message: string, title: string, duration?: number): Toast; static success(message: string, title: string, duration?: number): Toast
static error(message: string, title: string, duration?: number): Toast; static error(message: string, title: string, duration?: number): Toast
} }
class Resource { class Resource {
text: string; text: string
key: string; key: string
dependencies: Array<Resource>; dependencies: Array<Resource>
styles: Array<Resource>; styles: Array<Resource>
displayName: string; displayName: string
dropdown: object; dropdown: object
downloaded: boolean; downloaded: boolean
constructor(url: string, styles?: Resource[]); constructor(url: string, styles?: Resource[])
download(): Promise<string>; download(): Promise<string>
getStyle(id: string): string; getStyle(id: string): string
getPriorStyle(): any; getPriorStyle(): any
applyStyle(id: string, important: boolean): void; applyStyle(id: string, important: boolean): void
static all: object; static all: object
static displayNames: object; static displayNames: object
static manifest: object; static manifest: object
static root: string; static root: string
} }
class ResourceManager { class ResourceManager {
import(compnentName: string): any; import(compnentName: string): any
getDefaultStyleId(key: string): string; getDefaultStyleId(key: string): string
applyStyle(key: string, id?: string): void; applyStyle(key: string, id?: string): void
removeStyle(key: string): void; removeStyle(key: string): void
applyImportantStyle(key: string, id?: string): void; applyImportantStyle(key: string, id?: string): void
applyStyleFromText(text: string, id: string): void; applyStyleFromText(text: string, id: string): void
applyImportantStyleFromText(text: string, id: string): void; applyImportantStyleFromText(text: string, id: string): void
getStyle(key: string, id?: string): void; getStyle(key: string, id?: string): void
toggleStyle(content: string, id: string): void; toggleStyle(content: string, id: string): void
toggleStyle(key: string): void; toggleStyle(key: string): void
applyDropdownOptions(): Promise<void>; applyDropdownOptions(): Promise<void>
} }
const resources: ResourceManager; const resources: ResourceManager
class DoubleClickEvent { class DoubleClickEvent {
constructor(handler: (e: MouseEvent) => void, singleClickHandler: (e: MouseEvent) => void); constructor(handler: (e: MouseEvent) => void, singleClickHandler: (e: MouseEvent) => void)
bind(element: Element): void; bind(element: Element): void
unbind(element: Element): void; unbind(element: Element): void
} }
class Ajax { class Ajax {
static send(xhr: XMLHttpRequest, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>; static send(xhr: XMLHttpRequest, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>
static getText(url: string): Promise<string>; static getText(url: string): Promise<string>
static getTextWithCredentials(url: string): Promise<string>; static getTextWithCredentials(url: string): Promise<string>
static getJson(url: string): Promise<any>; static getJson(url: string): Promise<any>
static getJsonWithCredentials(url: string): Promise<any>; static getJsonWithCredentials(url: string): Promise<any>
static getBlob(url: string): Promise<Blob>; static getBlob(url: string): Promise<Blob>
static getBlobWithCredentials(url: string): Promise<Blob>; static getBlobWithCredentials(url: string): Promise<Blob>
static postText(url: string, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>; static postText(url: string, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>
static postTextWithCredentials(url: string, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>; static postTextWithCredentials(url: string, body: string | Document | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | ReadableStream<Uint8Array>): Promise<string>
static postJson(url: string, json: any): Promise<any>; static postJson(url: string, json: any): Promise<any>
static postJsonWithCredentials(url: string, json: any): Promise<any>; static postJsonWithCredentials(url: string, json: any): Promise<any>
static monkey(details: MonkeyXhrBasicDetails): Promise<any>; static monkey(details: MonkeyXhrBasicDetails): Promise<any>
} }
type Observable = string | Node | Node[] | NodeList; type Observable = string | Node | Node[] | NodeList
class Observer { class Observer {
constructor(element: Element, callback: MutationCallback); constructor(element: Element, callback: MutationCallback)
start(): Observer; start(): Observer
stop(): Observer; stop(): Observer
forEach(callback: (observer: Observer) => void): void; forEach(callback: (observer: Observer) => void): void
add(element: Element): Observer; add(element: Element): Observer
options: MutationObserverInit; options: MutationObserverInit
static observe(observable: Observable, callback: MutationCallback, options: MutationObserverInit): Observer; static observe(observable: Observable, callback: MutationCallback, options: MutationObserverInit): Observer
static childList(observable: Observable, callback: MutationCallback): Observer; static childList(observable: Observable, callback: MutationCallback): Observer
static childListSubtree(observable: Observable, callback: MutationCallback): Observer; static childListSubtree(observable: Observable, callback: MutationCallback): Observer
static attributes(observable: Observable, callback: MutationCallback): Observer; static attributes(observable: Observable, callback: MutationCallback): Observer
static attributesSubtree(observable: Observable, callback: MutationCallback): Observer; static attributesSubtree(observable: Observable, callback: MutationCallback): Observer
static all(observable: Observable, callback: MutationCallback): Observer; static all(observable: Observable, callback: MutationCallback): Observer
static videoChange(callback: MutationCallback): Promise<void>; static videoChange(callback: MutationCallback): Promise<void>
} }
interface BilibiliEvolvedSettings { interface BilibiliEvolvedSettings {
useDarkStyle: boolean, useDarkStyle: boolean,
@ -417,14 +417,15 @@ declare global {
customStyles: CustomStyle[], customStyles: CustomStyle[],
simpleHomeCategoryOrders: SimpleHomeCategoryOrders, simpleHomeCategoryOrders: SimpleHomeCategoryOrders,
keymapJumpSeconds: number, keymapJumpSeconds: number,
urlParamsClean: boolean,
latestVersionLink: string, latestVersionLink: string,
currentVersion: string, currentVersion: string,
} }
const GM_info: MonkeyInfo; const GM_info: MonkeyInfo
function GM_xmlhttpRequest(details: MonkeyXhrDetails): { abort: () => void }; function GM_xmlhttpRequest(details: MonkeyXhrDetails): { abort: () => void }
function GM_setClipboard(data: any, info: string | { type?: string, mimetype?: string }): void; function GM_setClipboard(data: any, info: string | { type?: string, mimetype?: string }): void
function GM_setValue(name: keyof BilibiliEvolvedSettings, value: any): void; function GM_setValue(name: keyof BilibiliEvolvedSettings, value: any): void
function GM_getValue<T>(name: keyof BilibiliEvolvedSettings, defaultValue?: T): T; function GM_getValue<T>(name: keyof BilibiliEvolvedSettings, defaultValue?: T): T
const GM: { const GM: {
info: MonkeyInfo info: MonkeyInfo
xmlHttpRequest: typeof GM_xmlhttpRequest xmlHttpRequest: typeof GM_xmlhttpRequest
@ -432,28 +433,28 @@ declare global {
setValue: (name: keyof BilibiliEvolvedSettings, value: any) => Promise<void> setValue: (name: keyof BilibiliEvolvedSettings, value: any) => Promise<void>
getValue: <T>(name: keyof BilibiliEvolvedSettings, defaultValue?: T) => Promise<T> getValue: <T>(name: keyof BilibiliEvolvedSettings, defaultValue?: T) => Promise<T>
} }
const settings: BilibiliEvolvedSettings; const settings: BilibiliEvolvedSettings
const customNavbarDefaultOrders: CustomNavbarOrders; const customNavbarDefaultOrders: CustomNavbarOrders
const aria2RpcDefaultOption: RpcOption; const aria2RpcDefaultOption: RpcOption
const languageNameToCode: { [key: string]: string }; const languageNameToCode: { [key: string]: string }
const languageCodeToName: { [key: string]: string }; const languageCodeToName: { [key: string]: string }
function logError(message: Error | string): void; function logError(message: Error | string): void
function loadSettings(): void function loadSettings(): void
function addSettingsListener(key: keyof BilibiliEvolvedSettings, handler: (newValue: any, oldValue: any) => void, initCall?: boolean): void; function addSettingsListener(key: keyof BilibiliEvolvedSettings, handler: (newValue: any, oldValue: any) => void, initCall?: boolean): void
function removeSettingsListener(key: keyof BilibiliEvolvedSettings, handler: (newValue: any, oldValue: any) => void): void; function removeSettingsListener(key: keyof BilibiliEvolvedSettings, handler: (newValue: any, oldValue: any) => void): void
function raiseEvent(element: Element, eventName: string): void; function raiseEvent(element: Element, eventName: string): void
function loadLazyPanel(selector: string): Promise<void>; function loadLazyPanel(selector: string): Promise<void>
function loadDanmakuSettingsPanel(): Promise<void>; function loadDanmakuSettingsPanel(): Promise<void>
function contentLoaded(callback: () => void): void; function contentLoaded(callback: () => void): void
function fullyLoaded(callback: () => void): void; function fullyLoaded(callback: () => void): void
function fixed(number: number, precision?: number): string; function fixed(number: number, precision?: number): string
function isEmbeddedPlayer(): boolean; function isEmbeddedPlayer(): boolean
function isIframe(): boolean; function isIframe(): boolean
function getI18nKey(): string; function getI18nKey(): string
function dq(selector: string): Element | null; function dq(selector: string): Element | null
function dq(element: Element, selector: string): Element | null; function dq(element: Element, selector: string): Element | null
function dqa(selector: string): Element[]; function dqa(selector: string): Element[]
function dqa(element: Element, selector: string): Element[]; function dqa(element: Element, selector: string): Element[]
function html(strings: TemplateStringsArray, ...values: unknown[]): string function html(strings: TemplateStringsArray, ...values: unknown[]): string
const formatFileSize: (bytes: number, fixed?: number) => string const formatFileSize: (bytes: number, fixed?: number) => string
const formatDuration: (time: number, fixed?: number) => string const formatDuration: (time: number, fixed?: number) => string
@ -470,4 +471,4 @@ declare global {
type ScriptVersion = 'Stable' | 'Preview' | 'Offline' | 'Preview Offline' | 'Local' | 'Local preview' | 'Local stable' | 'Local offline' | 'Local preview offline' type ScriptVersion = 'Stable' | 'Preview' | 'Offline' | 'Preview Offline' | 'Local' | 'Local preview' | 'Local stable' | 'Local offline' | 'Local preview offline'
const scriptVersion: ScriptVersion const scriptVersion: ScriptVersion
} }
export { }; export { }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -72,7 +72,7 @@
"full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764", "full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764",
"full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37", "full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37",
"gui-settings.min.css": "5E8B45124CFC7C4AE69C90E7462A918C59DC90EB5DB3B1AFA90010D96813D1EF", "gui-settings.min.css": "5E8B45124CFC7C4AE69C90E7462A918C59DC90EB5DB3B1AFA90010D96813D1EF",
"gui-settings.min.html": "1E6D65A172D8EA7832458DE97653FF34CB895B8B857459C0C59AE655499E4FA3", "gui-settings.min.html": "36F47CEB9F55F4534516ABBF827F0748A6D1C4FD6683B04E09AA386776532153",
"gui-settings.min.js": "F16F00703C27B37A75255444D3C255222857FD8D5061598D80174B56F2F1EC6A", "gui-settings.min.js": "F16F00703C27B37A75255444D3C255222857FD8D5061598D80174B56F2F1EC6A",
"haruna-scale.min.js": "D046864416831B101582DD87E602AE21309FDE2DB64A8F24D57B6ADBE67E6D7B", "haruna-scale.min.js": "D046864416831B101582DD87E602AE21309FDE2DB64A8F24D57B6ADBE67E6D7B",
"hide-bangumi-reviews.min.js": "7265C0CE994FDA926355A9A4F9B207E7E68E749D47332F3C537EF93E97927A23", "hide-bangumi-reviews.min.js": "7265C0CE994FDA926355A9A4F9B207E7E68E749D47332F3C537EF93E97927A23",
@ -172,6 +172,7 @@
"trending-videos.min.js": "CBD579F9C07B5B612B50C1522F05CD8B49AE9E1F47BB95896FE91BB032656FB1", "trending-videos.min.js": "CBD579F9C07B5B612B50C1522F05CD8B49AE9E1F47BB95896FE91BB032656FB1",
"trending-videos.vue.min.js": "DA96C03E52FDA7561B23F072AB794453D72E3CED523F9F5374A16885445F9925", "trending-videos.vue.min.js": "DA96C03E52FDA7561B23F072AB794453D72E3CED523F9F5374A16885445F9925",
"tweets.min.css": "9015C1F165C91B9205ABBE4E8A3B5FA83DB1EB4B5CF2442846AF61E44FF178A8", "tweets.min.css": "9015C1F165C91B9205ABBE4E8A3B5FA83DB1EB4B5CF2442846AF61E44FF178A8",
"url-params-clean.min.js": "4819BF0209A252D690C8787B95312FF39D36E95FE9AE7894EFE9323B395D896C",
"v-checkbox.vue.min.js": "A23C35D5627009A29FD396A024442A19E37DEE70674BF3CE0FA377D781ED2231", "v-checkbox.vue.min.js": "A23C35D5627009A29FD396A024442A19E37DEE70674BF3CE0FA377D781ED2231",
"v-dropdown.vue.min.js": "D26B4A74515F53A34A3CB0590FC9683476D99FBBBB9647FDFCBF33E265C3F662", "v-dropdown.vue.min.js": "D26B4A74515F53A34A3CB0590FC9683476D99FBBBB9647FDFCBF33E265C3F662",
"video-card.vue.min.js": "9EBC38E9F9CD6BDE3CC031BB88F6447EB29E7D8A2E7C32159D7BDC6CFD956D74", "video-card.vue.min.js": "9EBC38E9F9CD6BDE3CC031BB88F6447EB29E7D8A2E7C32159D7BDC6CFD956D74",

Binary file not shown.

File diff suppressed because one or more lines are too long

1
min/url-params-clean.min.js vendored Normal file
View File

@ -0,0 +1 @@
(()=>{return(t,r)=>{const e=["spm_id_from","from_source","from","seid"];const s=location.search.substring(1).split("&");const o=s.filter(t=>{if(e.some(r=>t.startsWith(`${r}=`))){return false}return true}).join("&");history.pushState({},document.title,document.URL.replace(location.search,o?"?"+o:""))}})();

View File

@ -775,5 +775,11 @@ Resource.manifest = {
hideRelatedVideos: '隐藏视频推荐', hideRelatedVideos: '隐藏视频推荐',
}, },
}, },
urlParamsClean: {
path: 'url-params-clean.min.js',
displayNames: {
urlParamsClean: '网址参数清理',
},
}
} }
export const resourceManifest = Resource.manifest export const resourceManifest = Resource.manifest

View File

@ -197,6 +197,7 @@ export const settings = {
customStyles: [], customStyles: [],
simpleHomeCategoryOrders: { ...simpleHomeCategoryDefaultOrders }, simpleHomeCategoryOrders: { ...simpleHomeCategoryDefaultOrders },
keymapJumpSeconds: 85, keymapJumpSeconds: 85,
urlParamsClean: false,
cache: {}, cache: {},
} }
const fixedSettings = { const fixedSettings = {

View File

@ -123,6 +123,7 @@
<checkbox indent="0" key="selectableColumnText" dependencies=""></checkbox> <checkbox indent="0" key="selectableColumnText" dependencies=""></checkbox>
<checkbox indent="0" key="watchlaterExpireWarnings" dependencies=""></checkbox> <checkbox indent="0" key="watchlaterExpireWarnings" dependencies=""></checkbox>
<checkbox indent="0" key="autoMatchMedal" dependencies=""></checkbox> <checkbox indent="0" key="autoMatchMedal" dependencies=""></checkbox>
<checkbox indent="0" key="urlParamsClean" dependencies=""></checkbox>
<!-- <checkbox indent="0" key="noMiniVideoAutoplay" dependencies=""></checkbox> --> <!-- <checkbox indent="0" key="noMiniVideoAutoplay" dependencies=""></checkbox> -->
<category icon="touch">触摸</category> <category icon="touch">触摸</category>
<checkbox indent="0" key="touchNavBar" dependencies=""></checkbox> <checkbox indent="0" key="touchNavBar" dependencies=""></checkbox>

View File

@ -0,0 +1,14 @@
const blockParams = [
'spm_id_from',
'from_source',
'from',
'seid',
]
const urlParams = location.search.substring(1).split('&')
const filteredParams = urlParams.filter(p => {
if (blockParams.some(b => p.startsWith(`${b}=`))) {
return false
}
return true
}).join('&')
history.pushState({}, document.title, document.URL.replace(location.search, filteredParams ? ('?' + filteredParams) : ''))