From 0d7381f02ae2aa77b627eb67ae2129ca8d0feffd Mon Sep 17 00:00:00 2001 From: Kevin R Date: Wed, 27 Jul 2022 00:28:15 +0200 Subject: [PATCH] Fixed #191 Used first code snippets from ClearURLs v2: https://gitlab.com/ClearURLs/core/-/blob/master/src/utils/URLHashParams.ts --- CHANGELOG.md | 1 + core_js/tools.js | 8 +- core_js/utils/Multimap.d.ts | 21 +++++ core_js/utils/Multimap.js | 130 +++++++++++++++++++++++++++++++ core_js/utils/URLHashParams.d.ts | 13 ++++ core_js/utils/URLHashParams.js | 77 ++++++++++++++++++ manifest.json | 2 + 7 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 core_js/utils/Multimap.d.ts create mode 100644 core_js/utils/Multimap.js create mode 100644 core_js/utils/URLHashParams.d.ts create mode 100644 core_js/utils/URLHashParams.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f5c425..307ccb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [138](https://github.com/ClearURLs/Addon/issues/138) - [1177](https://gitlab.com/KevinRoebert/ClearUrls/-/issues/1177) - [234](https://github.com/ClearURLs/Addon/issues/234) +- [191](https://github.com/ClearURLs/Addon/issues/191) ## [1.24.1] - 2022-03-25 diff --git a/core_js/tools.js b/core_js/tools.js index c62b06d..3989982 100644 --- a/core_js/tools.js +++ b/core_js/tools.js @@ -120,14 +120,10 @@ function countFields(url) { /** * Extract the fragments from an url. * @param {URL} url URL as object - * @return {URLSearchParams} fragments as URLSearchParams object + * @return {URLHashParams} fragments as URLSearchParams object */ function extractFragments(url) { - if (url.hash) { - return new URLSearchParams(url.hash.slice(1)); - } else { - return new URLSearchParams(); - } + return new URLHashParams(url) } /** diff --git a/core_js/utils/Multimap.d.ts b/core_js/utils/Multimap.d.ts new file mode 100644 index 0000000..6ff55bf --- /dev/null +++ b/core_js/utils/Multimap.d.ts @@ -0,0 +1,21 @@ +/** + * Models a multimap backed by a {@link Set}. + */ +export default class Multimap implements Iterable<[K, V]> { + private _map; + private _size; + constructor(); + get size(): number; + get(key: K): Set; + put(key: K, value: V): boolean; + has(key: K): boolean; + hasEntry(key: K, value: V): boolean; + delete(key: K): boolean; + deleteEntry(key: K, value: V): boolean; + clear(): void; + entries(): IterableIterator<[K, V]>; + values(): IterableIterator; + keys(): IterableIterator; + forEach(callback: (this: T | this, key: K, value: V, map: this) => void, thisArg?: T): void; + [Symbol.iterator](): IterableIterator<[K, V]>; +} diff --git a/core_js/utils/Multimap.js b/core_js/utils/Multimap.js new file mode 100644 index 0000000..6658249 --- /dev/null +++ b/core_js/utils/Multimap.js @@ -0,0 +1,130 @@ +"use strict"; +/* + * ClearURLs + * Copyright (c) 2017-2022 Kevin Röbert. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Models a multimap backed by a {@link Set}. + */ +class Multimap { + constructor() { + Object.defineProperty(this, "_map", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_size", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this._size = 0; + this._map = new Map(); + } + get size() { + return this._size; + } + get(key) { + const values = this._map.get(key); + if (values) { + return new Set(values); + } + else { + return new Set(); + } + } + put(key, value) { + let values = this._map.get(key); + if (!values) { + values = new Set(); + } + const count = values.size; + values.add(value); + if (values.size === count) { + return false; + } + this._map.set(key, values); + this._size++; + return true; + } + has(key) { + return this._map.has(key); + } + hasEntry(key, value) { + const values = this._map.get(key); + if (!values) { + return false; + } + return values.has(value); + } + delete(key) { + const values = this._map.get(key); + if (values && this._map.delete(key)) { + this._size -= values.size; + return true; + } + return false; + } + deleteEntry(key, value) { + const values = this._map.get(key); + if (values) { + if (!values.delete(value)) { + return false; + } + this._size--; + return true; + } + return false; + } + clear() { + this._map.clear(); + this._size = 0; + } + entries() { + const self = this; + function* gen() { + for (const [key, values] of self._map.entries()) { + for (const value of values) { + yield [key, value]; + } + } + } + return gen(); + } + values() { + const self = this; + function* gen() { + for (const [, value] of self.entries()) { + yield value; + } + } + return gen(); + } + keys() { + return this._map.keys(); + } + forEach(callback, thisArg) { + for (const [key, value] of this.entries()) { + callback.call(thisArg === undefined ? this : thisArg, key, value, this); + } + } + [Symbol.iterator]() { + return this.entries(); + } +} diff --git a/core_js/utils/URLHashParams.d.ts b/core_js/utils/URLHashParams.d.ts new file mode 100644 index 0000000..88194d7 --- /dev/null +++ b/core_js/utils/URLHashParams.d.ts @@ -0,0 +1,13 @@ +/** + * Models a hash parameter of a given {@link URL}. + */ +export default class URLHashParams { + private _params; + constructor(url: URL); + append(name: string, value?: string | null): void; + delete(name: string): void; + get(name: string): string | null; + getAll(name: string): Set; + keys(): IterableIterator; + toString(): string; +} diff --git a/core_js/utils/URLHashParams.js b/core_js/utils/URLHashParams.js new file mode 100644 index 0000000..5afa78a --- /dev/null +++ b/core_js/utils/URLHashParams.js @@ -0,0 +1,77 @@ +"use strict"; +/* + * ClearURLs + * Copyright (c) 2017-2022 Kevin Röbert. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Models a hash parameter of a given {@link URL}. + */ +class URLHashParams { + constructor(url) { + Object.defineProperty(this, "_params", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this._params = new Multimap(); + const hash = url.hash.slice(1); + const params = hash.split('&'); + for (const p of params) { + const param = p.split('='); + if (!param[0]) + continue; + const key = param[0]; + let value = null; + if (param.length === 2 && param[1]) { + value = param[1]; + } + this._params.put(key, value); + } + } + append(name, value = null) { + this._params.put(name, value); + } + delete(name) { + this._params.delete(name); + } + get(name) { + const [first] = this._params.get(name); + if (first) { + return first; + } + return null; + } + getAll(name) { + return this._params.get(name); + } + keys() { + return this._params.keys(); + } + toString() { + const rtn = []; + this._params.forEach((key, value) => { + if (value) { + rtn.push(key + '=' + value); + } + else { + rtn.push(key); + } + }); + return rtn.join('&'); + } +} diff --git a/manifest.json b/manifest.json index bbead78..df2bebe 100644 --- a/manifest.json +++ b/manifest.json @@ -57,6 +57,8 @@ "background": { "scripts": [ "browser-polyfill.js", + "core_js/utils/Multimap.js", + "core_js/utils/URLHashParams.js", "core_js/message_handler.js", "external_js/ip-range-check.js", "core_js/tools.js",