├── .github └── workflows │ └── ci.yml ├── CHANGELOG.md ├── LICENSE.md ├── MOZILLA.md ├── README.md ├── TODO.md ├── _locales ├── de │ └── messages.json ├── en │ └── messages.json ├── ja │ └── messages.json ├── nl │ └── messages.json ├── pt_BR │ └── messages.json ├── ru │ └── messages.json ├── uk │ └── messages.json └── zh_CN │ └── messages.json ├── background.js ├── browser-polyfill.min.js ├── build.sh ├── css ├── options.chrome.css ├── options.css └── options.firefox.css ├── data ├── default-params-by-category.json └── publicsuffix-ccSLD.txt ├── icons ├── dark │ ├── neaturl-48.png │ ├── neaturl-96-state-1.png │ ├── neaturl-96-state0.png │ ├── neaturl-96-state0_disabled.png │ ├── neaturl-96-state1.png │ ├── neaturl-96-state2.png │ └── neaturl-96-state3.png ├── light │ ├── neaturl-48.png │ ├── neaturl-96-state-1.png │ ├── neaturl-96-state0.png │ ├── neaturl-96-state0_disabled.png │ ├── neaturl-96-state1.png │ ├── neaturl-96-state2.png │ └── neaturl-96-state3.png ├── neaturl-48.png ├── neaturl-96-state-1.png ├── neaturl-96-state0.png ├── neaturl-96-state0_disabled.png ├── neaturl-96-state1.png ├── neaturl-96-state2.png └── neaturl-96-state3.png ├── images └── Neat URL 4.1.4 in Chrome.png ├── manifest.json ├── neaturl.js ├── options.html ├── options.js ├── package.json ├── shared.js ├── toolbaricon.js └── web-ext-artifacts ├── neat_url-1.0.0.zip ├── neat_url-1.0.1.zip ├── neat_url-1.1.0.zip ├── neat_url-1.2.0.zip ├── neat_url-2.0.0.zip ├── neat_url-2.0.1.zip ├── neat_url-2.0.2.zip ├── neat_url-2.0.3.zip ├── neat_url-2.0.4.zip ├── neat_url-2.0.5.zip ├── neat_url-2.1.0.zip ├── neat_url-2.1.1.zip ├── neat_url-2.1.2.zip ├── neat_url-3.0.0.zip ├── neat_url-3.1.0.zip ├── neat_url-3.1.1.zip ├── neat_url-3.2.0.zip ├── neat_url-4.0.0.zip ├── neat_url-4.0.1.zip ├── neat_url-4.1.0.zip ├── neat_url-4.1.1.zip ├── neat_url-4.1.2.zip ├── neat_url-4.1.3.zip ├── neat_url-4.1.4.chrome.zip ├── neat_url-4.1.4.firefox.zip ├── neat_url-4.1.5.chrome.zip ├── neat_url-4.1.5.firefox.zip ├── neat_url-5.0.0.chrome.zip ├── neat_url-5.0.0.firefox.zip ├── neat_url-6.0.0.chrome.zip └── neat_url-6.0.0.firefox.zip /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v2 18 | with: 19 | node-version: "lts/*" 20 | - name: Build 21 | run: | 22 | npm install web-ext 23 | npm run build:neat-url 24 | - name: Upload 25 | uses: actions/upload-artifact@v2 26 | with: 27 | path: web-ext-artifacts/neat_url-5.0.0.zip -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 6.1.0 (2024-09-?) 2 | ================== 3 | * Since 6.0.0 was never officially released, this contains all changes from 6.0.0 and more 4 | * Changes 5 | * Replace Promises by async/await code 6 | * Updated build script 7 | * Change homepage URL 8 | 9 | 6.0.0 (2022-02-07) 10 | ===== 11 | * New feature: rewrite URLs before you click on them (change links in page), fixes #26 (copy clean URL) and #262 (URL rewriting in DOM) 12 | * This is disabled by default and can be enabled in the Options (under Advanced) 13 | * New feature: fix #253 (clean 1Password littering of URLs): syntax KEY{length} added 14 | * New feature: Fix #256 (remove all parameters): wildcard parameter * is now supported 15 | 16 | * Updated default parameters 17 | * Fix #131 (add IMDb parameters) 18 | * Fix #145 (add guccounter@*.yahoo.com) 19 | * Inspired by #225 (investigate new parameters): added some rules 20 | * Fix #235 (TikTok rules): added rules 21 | * Fix #237 by #263 (add parameter ref_*@twitter.com) 22 | * Fix #241 (Linkedin email URLs): added numerous LinkedIn rules 23 | * Fix #246 (remove stm parameter): added parameter stm_* 24 | * Fix #250 (more parameters including at): added numerous parameters 25 | * Add parameter sc_cid (Adobe Analytics) (#230) 26 | * Fix #181 (add Amazon ascsubtag parameter) 27 | * Fix #170 (add AliExpress parameters) 28 | * Added dpg_* used by DPG Media 29 | * Add mtm_* used by Matomo/Piwik 30 | 31 | * Bugs fixed 32 | * Fix #258 (one letter parameter sometimes not blocked): this works as expected 33 | * Remove cid parameter, fixes #219, #226, #245, #251 and circumvents #248 34 | 35 | * Changes 36 | * LICENSE.md: Fix #155 and #260 (add GNU license) 37 | * README: updated default parameters 38 | * Options page: hide colorpicker for counter when default counter color is checked 39 | * Make more use of async/await code 40 | * Updated build script 41 | 42 | Special thanks to the contributors who made this version possible. 43 | 44 | 5.0.0 (2020-04-26) 45 | ===== 46 | * Fix #144 (XTOR): hash parameters work again 47 | * Fix #161 (Ebay): add Ebay parameter hash@ebay.* 48 | * Fix #167 (fbclid): add Facebook parameter fbclid 49 | * Fix #176 (Google Analytics): add Google Analytics parameters gclid, gclsrc 50 | * Fix #177 (merge commits) by updating this extension 51 | * Fix #200 (double domains) by using publicsuffix-ccSLD 52 | * Fix #204 (roadmap): consider this changelog to be the roadmap 53 | * Fix #205 (block all placeholders using #*): add support for #* and #?* 54 | * Fix #206 (Yandex parameters): added by default 55 | * Fix #207 (hash): hash parameters work again 56 | * Fix #216 (Matomo): add pk_* 57 | * Fix #217 (outdated) by updating this extension 58 | * Fix: mixing a root wild card domain with a suffix wildcard domain is now supported 59 | 60 | * Adding default blocking parameters in new versions results in all users receiving the new parameters 61 | * Existing default parameters included in the custom blocked parameters, will be deleted from the custom blocked parameters list 62 | * Organised default blocking parameters into categories and into a JSON file 63 | * This removes the need to have the default blocking list multiple times in the code base (options.js, background.js) 64 | 65 | * Added Twitch.tv parameters tt_medium, tt_content 66 | * Added MailChimp parameters mc_cid, mc_eid 67 | * Added Google parameters gs_gbg@google.*, gs_mss@google.*, gs_rn@google.*, gs_lcp@google.* 68 | * Added Google Analytics parameters gclid, gclsrc 69 | * Added Amazon parameter pf@amazon.* 70 | * Added AliExpress parameters algo_expid, algo_pvid, btsid, ws_ab_test 71 | * Added Omniture tracking parameter s_cid 72 | * Added Facebook parameters refsrc@facebook.com, hrc@facebook.com 73 | * Added Yandex parameters lr@yandex.*, redircnt@yandex.* 74 | * Added Ebay parameter hash@ebay.* 75 | * Removed terminal_id, CNDID since the use is unknown 76 | * Removed $/ref@amazon.* from the defaults due to suspected issues 77 | 78 | * Options page: Add parameter rules URL 79 | * Options page: Show default blocking parameters in a more organized way 80 | * Options page: slightly adapt CSS styles 81 | 82 | * README: update to the new default blocking parameters and use the new JSON format 83 | * README: root wildcard domain and suffix wildcard domain can be combined; added an example 84 | * README: organised "recommended parameters" 85 | * README: added an explanation about addons.mozilla.org (related to #198) 86 | 87 | 4.1.5 88 | ===== 89 | * Fix for item@jd.com 90 | 91 | 4.1.4 92 | ===== 93 | * Port to Chrome 94 | * Extract CSS into separate files 95 | 96 | 4.1.3 97 | ===== 98 | * Add _hsmi 99 | 100 | 4.1.2 101 | ===== 102 | * Remove ref, fixes #130 103 | 104 | 4.1.1 105 | ===== 106 | * Add spm@*.aliexpress.com, scm@*.aliexpress.com, aff_platform, aff_trace_key and terminal_id, fixes #103 107 | 108 | 4.1.0 109 | ===== 110 | * Add source@sourceforge.net, position@sourceforge.net, callback@bilibili.com, fixes #116 111 | * Fix #97 revert counter color to default color 112 | * Add eloqua tracking parameters #105 113 | * Exception support #111 114 | * Fix Neat URL breaks Google Product Forums #122 115 | * Add ref, tag@amazon.*, ref_@amazon.* and pf_rd_*@amazon.* by default (fixes #118 #120 #125) 116 | * Drop pd_rd_r@amazon.*, pd_rd_w@amazon.*, pd_rd_wg@amazon.* in favor of pd_rd_*@amazon.* (including automatic upgrade path) 117 | 118 | 4.0.1 119 | ===== 120 | * Fix ending parameters not detected when there are no query or hash parameters 121 | * Fix regression: Amazon product pages are not cleaned when not all parameters are included 122 | * Remove unused method parameters passed to removeEndings function 123 | 124 | 4.0.0 125 | ===== 126 | * Performance improvements 127 | * Several encoding bugs fixed #73 #75 #93 128 | * Re-initialise listener, hopefully fixes #92 129 | * Fix "Show counter" setting (introduced in 3.2.0) doesn't do anything #91 130 | * Workaround for gws_rd@google.* on google.com #76 131 | * Implement hash parameters using #? #83 132 | * Cleanups 133 | * Fix translation string mapped to wrong i18n id 134 | * Move most functions related to the toolbar button to a separate file 135 | * Automatically remove newlines from the Blocked parameters textarea when saving 136 | 137 | 3.2.0 138 | ===== 139 | * Add counter which shows the number of rewritten URLs 140 | * Add option to show/hide counter 141 | * Add option to set the counter background color 142 | * Fix addons.mozilla.org logic and change applyAfter to 1000ms 143 | * Drop tracking feature introduced in 3.1.0 144 | * Add blacklist feature to skip certain URLs 145 | * Skip rewriting urls which contain ?? 146 | * Empty list of request types now means no request types are filtered at all 147 | 148 | 3.1.1 149 | ===== 150 | * Fix handling of addons.mozilla.org again, browser.tabs.update triggers a new request, catch that 151 | * Change applyAfter from 400ms to 300ms on addons.mozilla.org 152 | 153 | 3.1.0 154 | ===== 155 | * Fix some websites breaking / problems caused by the use of URL() constructor #52 156 | * Default request filter will now only filter "main_frame" requests - see the advanced section of the options to change that (tip: if you want all requests to be filtered, you can use an empty value - it might break some sites, so make sure you report all URLs which do not work in this mode). #48 #52 livejournal.com 157 | * Safer handling of addons.mozilla.org - only main_frame requests will be changed to prevent issues. #48 158 | * Added tracking protection - it will cancel requests to listed domains 159 | * Expanded existing localisations 160 | * Explicit support for stripping of # parameters 161 | * Fix double dollar support 162 | 163 | 3.0.0 164 | ===== 165 | * Fix notification theme not respected the first time you click Save preferences when it is different from the default icon theme 166 | * Add utm_name, utm_pubreferrer, utm_swu, utm_viz_id to Neat URL defaults #43 167 | * Add hmb_campaign, hmb_medium, hmb_source to Neat URL defaults #43 168 | * Do not remove hash fragments #47 169 | * Implement wildcards at the end of the parameter (but before the domain @ sign). For example, utm_* 170 | * Fix bug in changed=false logic 171 | * Allow logging the changed URLs to the console #36 172 | * Add localisation system. The Dutch localisation is already included. 173 | * Expanded README with extra parameters #43 174 | * Ignore utm.gif links 175 | 176 | 2.1.2 177 | ===== 178 | * Fix problem with URL decoding 179 | * Keys are now case sensitive 180 | 181 | 2.1.1 182 | ===== 183 | * Do not update a tab to an empty URL 184 | 185 | 2.1.0 186 | ===== 187 | * Fix handling of addons.mozilla.org and mozilla.org again 188 | * On Amazon product pages, all parameters are removed 189 | * Add light icons for dark themes, can be set in the options 190 | 191 | 2.0.5 192 | ===== 193 | * Fix handling of mozilla.org 194 | 195 | 2.0.4 196 | ===== 197 | * Fix problem related to Google Docs - see https://addons.mozilla.org/nl/firefox/addon/neat-url/reviews/918997/ 198 | * Add _hsenc and mkt_tok to Neat URL defaults 199 | 200 | 2.0.3 201 | ===== 202 | * Important bugfix preventing some users from getting upgraded parameters 203 | 204 | 2.0.2 205 | ===== 206 | * Add utm_cid for mashable.com 207 | 208 | 2.0.1 209 | ===== 210 | * Introduce $$ to force remove everything after a certain string 211 | * Change $ behaviour to remove everything after a certain string only if there are no query parameters after reducing the query parameters (no longer breaks Amazon links) 212 | * Drop utils/compareVersions.js (no longer needed) 213 | 214 | 2.0.0 215 | ===== 216 | * Added domain wildcards 217 | * Added support for anchor tags 218 | * Made upgrading of parameters between versions more robust 219 | * Fixed context menu listeners staying attached after removing them 220 | * Add gs_l parameter retroactively 221 | * Add new default parameters: pd_rd_r@amazon.*, pd_rd_w@amazon.*, pd_rd_wg@amazon.*, _encoding@amazon.*, psc@amazon.*, ved@google.*, ei@google.*, sei@google.*, gws_rd@google.*, cvid@bing.com, form@bing.com, sk@bing.com, sp@bing.com, sc@bing.com, qs@bing.com, pq@bing.com, feature@youtube.com, gclid@youtube.com, kw@youtube.com, $/ref@amazon.* 222 | * Expanded README 223 | 224 | 1.2.0 225 | ===== 226 | - Fix options.js resizing of textarea width under certain conditions 227 | - Add parameter gs_l and provide an automatic upgrade path for users using earlier versions 228 | 229 | 1.1.0 230 | ===== 231 | - Support for addons.mozilla.org - try https://addons.mozilla.org/firefox/addon/google-pdf-viewer/?src=search after adding src@addons.mozilla.org to parameters in the options page 232 | - Fix support for google.co.uk (double domains) 233 | - Introduce support for root domains with subdomains. This means you can use wildcards at the beginning of a parameter (*.mozilla.org) 234 | 235 | 1.0.1 236 | ===== 237 | - Added utm_userid as default parameter 238 | 239 | 1.0.0 240 | ===== 241 | - Fork of Lean URL, with features from Pure URL 242 | - Added ability to set your own URL parameters on the options page (to reach feature parity with Pure URL) 243 | - Fixed version of Lean URL, works with recent Firefox versions 244 | - Added a nice animation in the toolbar (can be changed or disabled) 245 | - Added domain-specific blocked parameters (to reach feature parity with Pure URL) 246 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | == Neat URL == 2 | 3 | Copyright (C) Geoffrey De Belie and contributors 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License along 16 | with this program; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | 19 | See the full license text here: https://www.gnu.org/licenses/gpl-2.0.txt 20 | -------------------------------------------------------------------------------- /MOZILLA.md: -------------------------------------------------------------------------------- 1 | 3f3ecc7fad3545bbbb07551143aafee9 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Neat URL 2 | 3 | Neat URL is a browser extension that cleans URLs, removing parameters such as Google Analytics' utm parameters. [Download for Firefox][] or [download for Chrome][]. 4 | 5 | [Download for Firefox]: https://addons.mozilla.org/en-US/firefox/addon/neat-url/ 6 | [Download for Chrome]: https://chrome.google.com/webstore/detail/neat-url/jchobbjgibcahbheicfocecmhocglkco 7 | 8 | ## Example 9 | 10 | Before: 11 | * https://www.phoronix.com/scan.php?page=news_item&px=Ioquake3-Auto-Updater&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+Phoronix+(Phoronix) 12 | 13 | After: 14 | * https://www.phoronix.com/scan.php?page=news_item&px=Ioquake3-Auto-Updater 15 | 16 | ## Why should I use this? 17 | 18 | Are you tired of handing over data to Google or other companies? 19 | 20 | Do you want to see neater URLs? 21 | 22 | Neat URL is just what you're looking for! 23 | 24 | ## Default blocked parameters 25 | 26 | [See the default configuration here](./data/default-params-by-category.json) 27 | 28 | ## Parameter rules 29 | A parameter is something that starts with ?. You can add your own parameter in the options of Neat URL. The ? is ommitted in the options, so a ?ved parameter becomes "ved". There are a few exceptions to this rule (see below) 30 | 31 | Parameters can be global (for every domain): 32 | 33 | utm_source 34 | 35 | Parameters can contain @ signs (domain-specific): 36 | 37 | nb@tweakers.net 38 | 39 | Parameters can contain @ signs with a wildcard so every subdomain will match too (root wildcard domain): 40 | 41 | param@*.wired.com 42 | 43 | Parameters can contain @ signs with a wildcard at the end of a domain name (matches every domain name which begins with "google" and ends in an unknown suffix, called suffix wildcard domain): 44 | 45 | param@google.* 46 | 47 | Mixing a root wild card domain with a suffix wildcard domain in the same parameter is also possible: 48 | 49 | param@*.google.* (too many wildcards) 50 | 51 | Parameters can contain a wildcard at the end or before the domain sign: 52 | 53 | utm_* 54 | utm_*@omgubuntu.co.uk 55 | *@omgubuntu.co.uk 56 | 57 | Parameters can also apply globally (first rule), except for a (wildcard) domain (second rule): 58 | 59 | ref 60 | !ref@amazon.co.uk 61 | 62 | The excluded domain always takes precedence. Should you include "ref" and "!ref", "!ref" will apply. 63 | 64 | Other valid parameters - ending parameters (exceptions to the ? rule): 65 | 66 | ||| 67 | | --- | --- | 68 | | `$/ref@amazon.*` | remove everything after `/ref` on Amazon domains - this will only apply when there are no query parameters left after removing the filtered query parameters. \n\nException: Amazon product pages parameters are cleaned like they contain two dollar signs | 69 | | `$$/ref@amazon.*` | remove everything after `/ref` on Amazon domains - this will always apply, even when there are other query parameters after removing the filtered query parameters - this option is available because the user should be in control but beware that double dollar signs are dangerous, it might break the URL | 70 | 71 | Other valid parameters - hash parameters (exceptions to the ? rule): 72 | 73 | ||| 74 | | --- | --- | 75 | | `#xtor=RSS-8` | remove this parameter - be sure to include its value as well when you are using anchor tags | 76 | | `#xtor=RSS-8@futura-sciences.com` | for example this URL https://www.futura-sciences.com/magazines/espace/infos/actu/d/astronautique-curiosity-franchi-succes-dune-dingo-gap-52289/#xtor=RSS-8 | 77 | | `#?pk_campaign` | normal parameters that come after a hash sign, for example this URL https://vivaldi.com/blog/teamblog/vivaldi-1-13-adds-window-panel/#pk_campaign=newsletter&pk_kwd=community gets changed to https://vivaldi.com/blog/teamblog/vivaldi-1-13-adds-window-panel/#pk_kwd=community | 78 | | `#?pk_campaign@vivaldi.com` | same as above, but domain-matched instead of global | 79 | 80 | Invalid parameters: 81 | 82 | ||| 83 | | --- | --- | 84 | | `\|ved` | this is some random string - not supported, it will not work | 85 | | `/ref@amazon.*$` | dollar sign should be at the beginning | 86 | | `ref@*` | domain cannot be a wildcard, use ref instead to apply globally | 87 | 88 | ## Recommended parameters 89 | Parameters meant for the general public are included as default blocked parameters. You can add your own parameters for specific websites that are not (yet) supported by default. Parameters with only one or two letters will never be included in Neat URL by default, unless they can be given a domain. 90 | 91 | For Tweakers.net: 92 | nb@tweakers.net, u@tweakers.net 93 | 94 | For Vivaldi.com: 95 | #?pk_campaign@vivaldi.com, #?pk_kwd@vivaldi.com 96 | 97 | Google Analytics - tracking 98 | https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters 99 | 100 | tid, aip, ds, qt, uid, uip, ua, geoid, dr, cn, cs, cm, ck, cc, ci, gclid, dclid, linkid 101 | cid (campaign id, but used for other purposes by other websites - not included by default anymore) 102 | 103 | Google (possibly tracking) 104 | * aqs (https://superuser.com/questions/653295/what-is-the-aqs-parameter-in-google-search-query) 105 | * psi (possibly Page Speed Insights - possibly tracking) 106 | 107 | Google (tracking status unknown) 108 | * bav, bih, biw, ech (https://www.google.be/webhp?bav=on.2,or.r_qf.&biw=1920&bih=957&dpr=1&ech=1&psi=sXm9VNzfM8LYaqTigegJ.1421703563661.3&ei=sXm9VNzfM8LYaqTigegJ&emsg=NCSR&noj=1) 109 | * bvm, csi, cp, dpr, dq, forward, iact, ndsp, pbx, pq, sa, scroll, sclient, stick, vet, yv (https://greasyfork.org/en/scripts/31223-remove-google-tracking-uwaa/code) 110 | * tbnid 111 | 112 | Google (non tracking) 113 | * oq (original query) 114 | * prmd (type of search - https://revadigital.com/2012/06/the-complicated-nature-of-google-urls/) 115 | * npa, sc, z (Disabling Advertising Personalization - https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters) 116 | 117 | Tracking 118 | * icid (https://www.kshb.com/livevideo?ICID=ref_fark) 119 | * sr_share (SimpleReach - https://web.archive.org/web/20190817204709/http://docs.simplereach.com/how-tos-1/setting-up-tracking-parameters-for-social-distribution) 120 | 121 | For addons.mozilla.org: 122 | src@addons.mozilla.org, source@addons.mozilla.org, surveyversion@addons.mozilla.org, updateChannel@addons.mozilla.org, fxVersion@addons.mozilla.org, isDefaultBrowser@addons.mozilla.org, searchEngine@addons.mozilla.org, syncSetup@addons.mozilla.org, type@addons.mozilla.org, flowId@addons.mozilla.org 123 | 124 | (only works when extensions.webextensions.restrictedDomains is edited in about:config) 125 | (test URL https://support.mozilla.org/de/kb/enterprise-roots?as=u&utm_source=inproduct) 126 | 127 | Other parameters you can consider (website unknown) 128 | * iid 129 | * ijn 130 | * nid 131 | * ref_ 132 | 133 | ## Help, it does not work! 134 | * Have you checked that the syntax you are using is valid? 135 | * WebExtensions (like Neat URL) aren't allow to work on several Mozilla domains. This is a security feature. To allow all WebExtensions to work on these websites, you need to edit extensions.webextensions.restrictedDomains in about:config. 136 | 137 | ## History 138 | Neat URL is based on [Lean URL](https://github.com/xmikro/lean-url/). 139 | 140 | Neat URL contains a few improvements: 141 | * set your own URL parameters on the options page (to reach feature parity with Pure URL) 142 | * fixed for recent Firefox versions and compatible with Chrome 143 | * a nice animation and counter in the toolbar (can be changed or disabled) 144 | * domain-specific blocked parameters (to reach feature parity with Pure URL) 145 | * wildcard domain-specific blocked parameters 146 | * wildcard at the end of blocked parameters (general or domain-specific) 147 | * absolute wildcard parameter (domain-specific)) 148 | * expanded default blocked parameter offering 149 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | TODO 2 | ==== 3 | 4 | Not done currently, but on the roadmap for future versions. 5 | 6 | Browser support 7 | ==== 8 | 9 | * Migrate to Manifest V3 (to keep supporting Chrome) 10 | * Support for Microsoft Edge 11 | * Support for Android 12 | * Support for Firefox 13 | * Support for Kiwi Browser 14 | * Support for Vivaldi 15 | * Support for Thunderbird 16 | 17 | Bugs 18 | ==== 19 | * wt_zmc for https://advise.zeit.de/wp-content/uploads/2023/02/ZEITReisetraeume2023-2.pdf?wt_zmc=nl.int.zonaudev.77556405706_414236646305.nl_ref. 20 | 21 | New functionality 22 | ==== 23 | 24 | * Syntax ref=share@amazon.com 25 | * Import/export 26 | * Implement recursion (example.com?url=example2.com%3Futm%3Dsomething) 27 | -------------------------------------------------------------------------------- /_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Müll von URLs entfernen.", 4 | "description": "Beschreibung der Erweiterung." 5 | }, 6 | "default_blocked_params": { 7 | "message": "Default blocked parameters" 8 | }, 9 | "default_blocked_params_descr": { 10 | "message": "These are the default parameters that Neat URL will remove from the URL." 11 | }, 12 | "override_default_blocked_params": { 13 | "message": "Override list for default blocked parameters" 14 | }, 15 | "override_default_blocked_params_descr": { 16 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 17 | }, 18 | "blocked_params": { 19 | "message": "Blockierte Parameter" 20 | }, 21 | "blocked_params_descr": { 22 | "message": "Parameter (Groß-/Kleinschreibung wird beachtet), die von der URL entfernt werden. Benutze parameter@domain.com um domainspezifische blockierte Parameter zu verwenden. Benutze ein Komma als Trennzeichen zwischen blockierter Parameter.

Parameter rules" 23 | }, 24 | "icon_animation": { 25 | "message": "Icon-Animation" 26 | }, 27 | "icon_animation_descr": { 28 | "message": "Zu verwendende Animation, wenn Neat URL die URL säubert." 29 | }, 30 | "icon_animation_none": { 31 | "message": "Keine Animation" 32 | }, 33 | "icon_animation_missing_underscore": { 34 | "message": "Fehlender Unterstrich" 35 | }, 36 | "icon_animation_rotate": { 37 | "message": "Icon drehen" 38 | }, 39 | "icon_animation_surprise_me": { 40 | "message": "Überrasch mich" 41 | }, 42 | "icon_theme": { 43 | "message": "Icon-Theme" 44 | }, 45 | "icon_theme_descr": { 46 | "message": "Dunkle Icons werden standardmäßig verwenden. Du kannst diese Einstellungen ändern, um helle Icons zu verwenden." 47 | }, 48 | "icon_theme_dark": { 49 | "message": "Immer dunkle Icons verwenden" 50 | }, 51 | "icon_theme_light": { 52 | "message": "Immer helle Icons verwenden" 53 | }, 54 | "icon_theme_dark_notiflight": { 55 | "message": "Überall bis auf in Benachrichtigungen dunkle Icons verwenden", 56 | "description": "" 57 | }, 58 | "icon_theme_light_notifdark": { 59 | "message": "Überall bis auf in Benachrichtigungen helle Icons verwenden" 60 | }, 61 | "show_counter": { 62 | "message": "Zähler anzeigen" 63 | }, 64 | "show_counter_descr": { 65 | "message": "Einen Zähler anzeigen, der die Anzahl umgeschriebener URLS zeigt." 66 | }, 67 | "counter_background_color": { 68 | "message": "Zähler-Hintergrundfarbe" 69 | }, 70 | "counter_background_color_descr": { 71 | "message": "Die vom Zähler verwendete Hintergrundfarbe." 72 | }, 73 | "enable_logging": { 74 | "message": "Logging aktivieren" 75 | }, 76 | "enable_logging_descr": { 77 | "message": "URL-Veränderungen in die Browserkonsole loggen." 78 | }, 79 | "advanced": { 80 | "message": "Erweitert" 81 | }, 82 | "advanced_descr": { 83 | "message": "Diese Optionen können beißen." 84 | }, 85 | "theme": { 86 | "message": "Thema" 87 | }, 88 | "theme_descr": { 89 | "message": "Themenoptionen für Symbole und Benachrichtigungen." 90 | }, 91 | "blacklist": { 92 | "message": "Domain-Sperrliste" 93 | }, 94 | "blacklist_descr": { 95 | "message": "Durch Komma getrennte Liste an Domains. Neat URL wird auf diesen Webseiten nicht arbeiten." 96 | }, 97 | "url_request_types": { 98 | "message": "URL-Anfrage-Typen" 99 | }, 100 | "url_request_types_descr": { 101 | "message": "Standardwert: main_frame. Diese Liste ist kommasepariert. Gültige Werte können in der Liste von Ressourcen-Typen gefunden werden.", 102 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 103 | }, 104 | "counter_default_color": { 105 | "message": "Die standardmäßige Zähler-Farbe verwenden" 106 | }, 107 | "savepreferences": { 108 | "message": "Einstellungen speichern" 109 | }, 110 | "notify_preferences_saved": { 111 | "message": "Einstellungen gespeichert" 112 | }, 113 | "change_links_in_page": { 114 | "message": "Change links in page" 115 | }, 116 | "change_links_in_page_descr": { 117 | "message": "Remove blocked parameters from all links when loading a page" 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Remove garbage from URLs." 4 | }, 5 | "default_blocked_params": { 6 | "message": "Default blocked parameters" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "These are the default parameters that Neat URL will remove from the URL." 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "Override list for default blocked parameters" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 16 | }, 17 | "blocked_params": { 18 | "message": "Blocked parameters" 19 | }, 20 | "blocked_params_descr": { 21 | "message": "Case-sensitive parameters that will be removed from the URL. Use param@domain.com to use domain-specific blocked parameters. Use a comma as the delimiter between blocked parameters.

Parameter rules" 22 | }, 23 | "icon_animation": { 24 | "message": "Icon animation" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Animation to use when Neat URL is cleaning up the URL." 28 | }, 29 | "icon_animation_none": { 30 | "message": "No animation" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "Missing underscore" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "Rotate icon" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "Surprise me" 40 | }, 41 | "icon_theme": { 42 | "message": "Icon theme" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "Dark icons are used by default. You can change this option to use light icons." 46 | }, 47 | "icon_theme_dark": { 48 | "message": "Always use dark icons" 49 | }, 50 | "icon_theme_light": { 51 | "message": "Always use light icons" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "Use dark icons except for notifications" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "Use light icons except for notifications" 58 | }, 59 | "show_counter": { 60 | "message": "Show counter" 61 | }, 62 | "show_counter_descr": { 63 | "message": "Show a counter which displays the number of rewritten URLs." 64 | }, 65 | "counter_background_color": { 66 | "message": "Counter background color" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "The background color used by the counter." 70 | }, 71 | "enable_logging": { 72 | "message": "Enable logging" 73 | }, 74 | "enable_logging_descr": { 75 | "message": "Log URL changes to the browser console." 76 | }, 77 | "advanced": { 78 | "message": "Advanced" 79 | }, 80 | "advanced_descr": { 81 | "message": "These options may bite." 82 | }, 83 | "theme": { 84 | "message": "Theme" 85 | }, 86 | "theme_descr": { 87 | "message": "Icon and notification theme options." 88 | }, 89 | "blacklist": { 90 | "message": "Domain blacklist" 91 | }, 92 | "blacklist_descr": { 93 | "message": "Comma separated list of domains. Neat URL will not work on these websites." 94 | }, 95 | "url_request_types": { 96 | "message": "URL request types" 97 | }, 98 | "url_request_types_descr": { 99 | "message": "Default value: main_frame. This list is comma-separated. Valid values can be found in the the list of resource types.", 100 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 101 | }, 102 | "counter_default_color": { 103 | "message": "Use the default counter color" 104 | }, 105 | "savepreferences": { 106 | "message": "Save preferences" 107 | }, 108 | "notify_preferences_saved": { 109 | "message": "Saved preferences" 110 | }, 111 | "change_links_in_page": { 112 | "message": "Change links in page" 113 | }, 114 | "change_links_in_page_descr": { 115 | "message": "Remove blocked parameters from all links when loading a page" 116 | } 117 | } -------------------------------------------------------------------------------- /_locales/ja/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "URLからごみを除去するします。" 4 | }, 5 | "default_blocked_params": { 6 | "message": "既定でブロックされるパラメーター" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "Neat URLがURLから削除する、既定のパラメータです。" 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "既定でブロックされるパラメーターの上書きリスト" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "既定でブロックされるパラメーターのうち、無効にしたいものをカンマで区切って書いて下さい。" 16 | }, 17 | "blocked_params": { 18 | "message": "ブロックされるパラメーター" 19 | }, 20 | "blocked_params_descr": { 21 | "message": "URLから削除したいパラメーターを、カンマで区切って書いて下さい。大文字と小文字は区別されます。ドメインを指定してブロックしたパラメーターを設定する場合は、param@domain.comの書式を使用してください。

パラメーターの規則" 22 | }, 23 | "icon_animation": { 24 | "message": "アイコンのアニメーション" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Neat URLがURLをクリーンアップするときに使用するアニメーションです。" 28 | }, 29 | "icon_animation_none": { 30 | "message": "アニメーションなし" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "アンダースコアを消す" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "アイコンを回転する" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "おまかせ" 40 | }, 41 | "icon_theme": { 42 | "message": "アイコンのテーマ" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "既定では暗いアイコンが使用されます。明るいアイコンに変更することができます。" 46 | }, 47 | "icon_theme_dark": { 48 | "message": "常に暗いアイコンを使用する" 49 | }, 50 | "icon_theme_light": { 51 | "message": "常に明るいアイコンを使用する" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "通知を除いて、暗いアイコンを使用する" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "通知を除いて、明るいアイコンを使用する" 58 | }, 59 | "show_counter": { 60 | "message": "カウンターを表示" 61 | }, 62 | "show_counter_descr": { 63 | "message": "書き換えたURLの数を示すカウンターを表示します。" 64 | }, 65 | "counter_background_color": { 66 | "message": "カウンターの背景色" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "カウンターが使用する背景色です。" 70 | }, 71 | "enable_logging": { 72 | "message": "ログを有効にする" 73 | }, 74 | "enable_logging_descr": { 75 | "message": "URLの変更をブラウザのコンソールにログ出力します。" 76 | }, 77 | "advanced": { 78 | "message": "高度な設定" 79 | }, 80 | "advanced_descr": { 81 | "message": "これらのオプションは悪い影響を及ぼすかもしれません。" 82 | }, 83 | "theme": { 84 | "message": "テーマ" 85 | }, 86 | "theme_descr": { 87 | "message": "アイコンと通知のテーマに関するオプションです。" 88 | }, 89 | "blacklist": { 90 | "message": "ドメインのブロックリスト" 91 | }, 92 | "blacklist_descr": { 93 | "message": "カンマで区切られたドメインのリストです。Neat URLは、これらのウェブサイトでは作動しません。" 94 | }, 95 | "url_request_types": { 96 | "message": "URLのリクエスト型" 97 | }, 98 | "url_request_types_descr": { 99 | "message": "既定値: main_frame. このリストはカンマで区切られています。有効な値は、the list of resource types (en-US)で確認することができます。", 100 | "description": "リンクはそのままにしておいてください。通常のテキストと 'the list of resource types' というテキストを翻訳することができます。リンクは変更しないでください。main_frameもそのままにしてください。" 101 | }, 102 | "counter_default_color": { 103 | "message": "既定のカウンター色を使用する" 104 | }, 105 | "savepreferences": { 106 | "message": "設定を保存します" 107 | }, 108 | "notify_preferences_saved": { 109 | "message": "設定を保存しました" 110 | }, 111 | "change_links_in_page": { 112 | "message": "ページ内リンクを変更する" 113 | }, 114 | "change_links_in_page_descr": { 115 | "message": "ページを読み込む時に、ブロックされたパラメータを全てのリンクから削除します" 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /_locales/nl/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Verwijder rommel van URLs." 4 | }, 5 | "default_blocked_params": { 6 | "message": "Standaard geblokkeerde parameters" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "These are the default parameters that Neat URL will remove from the URL." 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "Override list for default blocked parameters" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 16 | }, 17 | "blocked_params": { 18 | "message": "Geblokkeerde parameters" 19 | }, 20 | "blocked_params_descr": { 21 | "message": "Hoofdlettergevoelige parameters die uit de URL verwijderd zullen worden. Gebruik parameter@domein.com om domeinspecifieke geblokkeerde parameters te gebruiken. Gebruik een komma als scheidingsteken tussen geblokkeerde parameters.

Parameter rules" 22 | }, 23 | "icon_animation": { 24 | "message": "Icoonanimatie" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Animatie die gebruikt wordt terwijl Neat URL de URL opschoont." 28 | }, 29 | "icon_animation_none": { 30 | "message": "Geen animatie" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "Ontbrekende underscore" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "Roteer icoon" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "Verras me" 40 | }, 41 | "icon_theme": { 42 | "message": "Icoonthema" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "Donkere icoontjes worden standaard gebruikt. Je kan deze optie veranderen om lichte icoontjes te gebruiken." 46 | }, 47 | "icon_theme_dark": { 48 | "message": "Gebruik altijd donkere icoontjes" 49 | }, 50 | "icon_theme_light": { 51 | "message": "Gebruik altijd lichte icoontjes" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "Gebruik donkere icoontjes behalve voor notificaties" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "Gebruik lichte icoontjes behalve voor notificaties" 58 | }, 59 | "show_counter": { 60 | "message": "Toon teller" 61 | }, 62 | "show_counter_descr": { 63 | "message": "Toon een teller die het aantal herschreven URLs toont." 64 | }, 65 | "counter_background_color": { 66 | "message": "Achtergrondkleur teller" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "De achtergrondkleur die gebruikt wordt door de teller." 70 | }, 71 | "enable_logging": { 72 | "message": "Zet logging aan" 73 | }, 74 | "enable_logging_descr": { 75 | "message": "Log URL-veranderingen naar de browserconsole." 76 | }, 77 | "advanced": { 78 | "message": "Geavanceerd" 79 | }, 80 | "advanced_descr": { 81 | "message": "Deze opties kunnen bijten." 82 | }, 83 | "theme": { 84 | "message": "Thema" 85 | }, 86 | "theme_descr": { 87 | "message": "Opties voor het icoon- en meldingenthema." 88 | }, 89 | "blacklist": { 90 | "message": "Zwarte lijst van domeinen" 91 | }, 92 | "blacklist_descr": { 93 | "message": "Kommagescheiden lijst van domeinen. Neat URL zal niet werken op deze websites." 94 | }, 95 | "url_request_types": { 96 | "message": "URL-aanvraagtypes" 97 | }, 98 | "url_request_types_descr": { 99 | "message": "Standaardwaarde: main_frame. Deze lijst is kommagescheiden. Geldige waardes kunnen gevonden worden in de lijst van aanvraagtypes.", 100 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 101 | }, 102 | "counter_default_color": { 103 | "message": "Gebruik de standaard achtergrondkleur voor de teller" 104 | }, 105 | "savepreferences": { 106 | "message": "Voorkeuren opslaan" 107 | }, 108 | "notify_preferences_saved": { 109 | "message": "Voorkeuren opgeslagen" 110 | }, 111 | "change_links_in_page": { 112 | "message": "Change links in page" 113 | }, 114 | "change_links_in_page_descr": { 115 | "message": "Remove blocked parameters from all links when loading a page" 116 | } 117 | } -------------------------------------------------------------------------------- /_locales/pt_BR/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Remove rastreamento de URLs." 4 | }, 5 | "default_blocked_params": { 6 | "message": "Parâmetros bloqueados por padrão" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "Parâmetros predefinidos que Neat URL removerá de URL." 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "Lista a ser ignorada em parâmetros bloqueados por padrão" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "Para excluir parâmetros que fazem parte de parâmetros bloqueados por padrão, adicione-os aqui. Use uma vírgula como delimitador entre os parâmetros a serem removidos de bloqueados por padrão." 16 | }, 17 | "blocked_params": { 18 | "message": "Parâmetros bloqueados" 19 | }, 20 | "blocked_params_descr": { 21 | "message": "Parâmetros sensíveis a maiúsculas que serão removidos de URL. Use param@domain.com para utilizar parâmetros bloqueados específicos de domínio. Use uma vírgula como delimitador entre os parâmetros bloqueados.

Regras de parâmetros" 22 | }, 23 | "icon_animation": { 24 | "message": "Animação do ícone" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Animação a ser usada quando Neat URL estiver limpando URL." 28 | }, 29 | "icon_animation_none": { 30 | "message": "Nenhuma animação" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "Sublinho em falta" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "Girar ícone" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "Surpreenda-me" 40 | }, 41 | "icon_theme": { 42 | "message": "Tema do ícone" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "Ícones escuros são usados por padrão. Você pode mudar esta opção e usar ícones claros." 46 | }, 47 | "icon_theme_dark": { 48 | "message": "Usar sempre ícones escuros" 49 | }, 50 | "icon_theme_light": { 51 | "message": "Usar sempre ícones claros" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "Usar ícones escuros exceto para notificações" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "Usar ícones claros exceto para notificações" 58 | }, 59 | "show_counter": { 60 | "message": "Mostrar contador" 61 | }, 62 | "show_counter_descr": { 63 | "message": "Mostrar um contador que exibe o número de URLs refeitas." 64 | }, 65 | "counter_background_color": { 66 | "message": "Cor de fundo do contador" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "A cor de fundo usada pelo contador." 70 | }, 71 | "enable_logging": { 72 | "message": "Ativar registros" 73 | }, 74 | "enable_logging_descr": { 75 | "message": "Registrar mudanças de URL no console de navegador." 76 | }, 77 | "advanced": { 78 | "message": "Avançado" 79 | }, 80 | "advanced_descr": { 81 | "message": "Estas opções podem morder." 82 | }, 83 | "theme": { 84 | "message": "Tema" 85 | }, 86 | "theme_descr": { 87 | "message": "Opções de tema para ícone e notificação." 88 | }, 89 | "blacklist": { 90 | "message": "Lista de domínios proibidos" 91 | }, 92 | "blacklist_descr": { 93 | "message": "Lista de domínios separada por vírgula. O Neat URL não funcionará nestes sites." 94 | }, 95 | "url_request_types": { 96 | "message": "Tipos de solicitação de URL" 97 | }, 98 | "url_request_types_descr": { 99 | "message": "Valor padrão: main_frame. Esta lista é separada por vírgulas. Os valores válidos podem ser encontrados na lista de tipos de recursos.", 100 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 101 | }, 102 | "counter_default_color": { 103 | "message": "Use a cor padrão do contador" 104 | }, 105 | "savepreferences": { 106 | "message": "Salvar preferências" 107 | }, 108 | "notify_preferences_saved": { 109 | "message": "Preferências salvas" 110 | }, 111 | "change_links_in_page": { 112 | "message": "Alterar links no site" 113 | }, 114 | "change_links_in_page_descr": { 115 | "message": "Remover parâmetros bloqueados de todos os links ao carregar um site" 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /_locales/ru/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Удаляет мусор из URL." 4 | }, 5 | "default_blocked_params": { 6 | "message": "Default blocked parameters (EN)" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "These are the default parameters that Neat URL will remove from the URL. (EN)" 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "Override list for default blocked parameters" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 16 | }, 17 | "blocked_params": { 18 | "message": "Заблокированные параметры URL-адресов." 19 | }, 20 | "blocked_params_descr": { 21 | "message": "Чувствительные к регистру параметры, которые будут удалены из URL. Используйте шаблон param@domain.com чтобы применять удаление параметров для конкретных доменов. Разделяйте отдельные параметры запятой.

Parameter rules" 22 | }, 23 | "icon_animation": { 24 | "message": "Анимация значка" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Анимация, которую нужно использовать, когда Neat URL очищает URL-адрес." 28 | }, 29 | "icon_animation_none": { 30 | "message": "Без анимации" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "Мигающий знак подчёркивания" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "Вращение значка" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "Удивите меня" 40 | }, 41 | "icon_theme": { 42 | "message": "Тема значка" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "Тёмные значки используются по умолчанию. Вы можете изменить этот параметр, чтобы использовать светлые значки." 46 | }, 47 | "icon_theme_dark": { 48 | "message": "Всегда использовать тёмные значки" 49 | }, 50 | "icon_theme_light": { 51 | "message": "Всегда использовать светлые значки" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "Использовать тёмные значки, кроме уведомлений" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "Использовать светлые значки, кроме уведомлений" 58 | }, 59 | "show_counter": { 60 | "message": "Показывать счетчик" 61 | }, 62 | "show_counter_descr": { 63 | "message": "Показывать счетчик, отображающий количество исправленных url-адресов." 64 | }, 65 | "counter_background_color": { 66 | "message": "Цвет фона счетчика" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "Цвет фона, используемый счетчиком." 70 | }, 71 | "enable_logging": { 72 | "message": "Включить журналирование", 73 | "description": "" 74 | }, 75 | "enable_logging_descr": { 76 | "message": "Записывать изменения URL-адресов в консоль браузера" 77 | }, 78 | "advanced": { 79 | "message": "Дополнительно" 80 | }, 81 | "advanced_descr": { 82 | "message": "Это параметры для опытного пользователя." 83 | }, 84 | "theme": { 85 | "message": "Theme" 86 | }, 87 | "theme_descr": { 88 | "message": "Icon and notification theme options." 89 | }, 90 | "blacklist": { 91 | "message": "Черный список доменов" 92 | }, 93 | "blacklist_descr": { 94 | "message": "Список доменов, разделённый запятыми. Neat URL не будет срабатывать на этих сайтах." 95 | }, 96 | "url_request_types": { 97 | "message": "Типы URL-запросов" 98 | }, 99 | "url_request_types_descr": { 100 | "message": "Значение по умолчанию: main_frame. Этот список разделен запятыми. Допустимые значения можно найти здесь: the list of resource types.", 101 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 102 | }, 103 | "counter_default_color": { 104 | "message": "Use the default counter color" 105 | }, 106 | "savepreferences": { 107 | "message": "Сохранить настройки" 108 | }, 109 | "notify_preferences_saved": { 110 | "message": "Настройки сохранены" 111 | }, 112 | "change_links_in_page": { 113 | "message": "Change links in page" 114 | }, 115 | "change_links_in_page_descr": { 116 | "message": "Remove blocked parameters from all links when loading a page" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /_locales/uk/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "Видаляє сміття з URL-адрес.", 4 | "description": "Description of the extension." 5 | }, 6 | "default_blocked_params": { 7 | "message": "Default blocked parameters" 8 | }, 9 | "default_blocked_params_descr": { 10 | "message": "These are the default parameters that Neat URL will remove from the URL." 11 | }, 12 | "override_default_blocked_params": { 13 | "message": "Override list for default blocked parameters" 14 | }, 15 | "override_default_blocked_params_descr": { 16 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 17 | }, 18 | "blocked_params": { 19 | "message": "Заблоковані параметри URL-адрес." 20 | }, 21 | "blocked_params_descr": { 22 | "message": "Чутливі до регістру параметри, котрі будуть видалені з URL. Використовуйте шаблон param@domain.com щоб застосовувати видалення параметрів для конкретних доменів. Розділяйте окремі параметри комою.

Parameter rules" 23 | }, 24 | "icon_animation": { 25 | "message": "Анімація піктограми" 26 | }, 27 | "icon_animation_descr": { 28 | "message": "Анімація, яку потрібно використовувати, коли Neat URL очищає URL-адресу." 29 | }, 30 | "icon_animation_none": { 31 | "message": "Без анімації" 32 | }, 33 | "icon_animation_missing_underscore": { 34 | "message": "Блимаючий знак підкреслення" 35 | }, 36 | "icon_animation_rotate": { 37 | "message": "Обертання піктограми" 38 | }, 39 | "icon_animation_surprise_me": { 40 | "message": "Здивуйте мене" 41 | }, 42 | "icon_theme": { 43 | "message": "Тема піктограм" 44 | }, 45 | "icon_theme_descr": { 46 | "message": "Темні піктограми використовуються за замовчуванням. Ви можете змінити цей параметр, щоб використовувати світлі піктограми." 47 | }, 48 | "icon_theme_dark": { 49 | "message": "Завжди використовувати темні піктограми" 50 | }, 51 | "icon_theme_light": { 52 | "message": "Завжди використовувати світлі піктограми" 53 | }, 54 | "icon_theme_dark_notiflight": { 55 | "message": "Використовувати темні піктограми, крім сповіщень" 56 | }, 57 | "icon_theme_light_notifdark": { 58 | "message": "Використовувати світі піктограми, крім сповіщень" 59 | }, 60 | "show_counter": { 61 | "message": "Показувати лічильник" 62 | }, 63 | "show_counter_descr": { 64 | "message": "Показувати лічильник, що відображає кількість очищених url-адрес." 65 | }, 66 | "counter_background_color": { 67 | "message": "Колір фону лічильника" 68 | }, 69 | "counter_background_color_descr": { 70 | "message": "Колір фону, що використовується лічильником." 71 | }, 72 | "enable_logging": { 73 | "message": "Ввімкнути ведення журналу" 74 | }, 75 | "enable_logging_descr": { 76 | "message": "Записувати зміни URL-адрес в консоль браузера" 77 | }, 78 | "advanced": { 79 | "message": "Додатково" 80 | }, 81 | "advanced_descr": { 82 | "message": "Це параметри для досвідченого користувача." 83 | }, 84 | "theme": { 85 | "message": "Theme" 86 | }, 87 | "theme_descr": { 88 | "message": "Icon and notification theme options." 89 | }, 90 | "blacklist": { 91 | "message": "Чорний список доменів" 92 | }, 93 | "blacklist_descr": { 94 | "message": "Список доменів, розділений комами. Neat URL не буде спрацьовувати на цих веб-сайтах." 95 | }, 96 | "url_request_types": { 97 | "message": "Типи URL-запитів" 98 | }, 99 | "url_request_types_descr": { 100 | "message": "Значення за замовчуванням: main_frame. Цей список розділено комами. Допустимі значення можна знайти тут: the list of resource types.", 101 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 102 | }, 103 | "counter_default_color": { 104 | "message": "Use the default counter color" 105 | }, 106 | "savepreferences": { 107 | "message": "Зберегти налаштування" 108 | }, 109 | "notify_preferences_saved": { 110 | "message": "Налаштування збережено" 111 | }, 112 | "change_links_in_page": { 113 | "message": "Change links in page" 114 | }, 115 | "change_links_in_page_descr": { 116 | "message": "Remove blocked parameters from all links when loading a page" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /_locales/zh_CN/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionDescription": { 3 | "message": "移除网址中的无用段。" 4 | }, 5 | "default_blocked_params": { 6 | "message": "Default blocked parameters (EN)" 7 | }, 8 | "default_blocked_params_descr": { 9 | "message": "These are the default parameters that Neat URL will remove from the URL. (EN)" 10 | }, 11 | "override_default_blocked_params": { 12 | "message": "Override list for default blocked parameters" 13 | }, 14 | "override_default_blocked_params_descr": { 15 | "message": "To disable parameters that are part of the default blocked parameters, add them here. Use a comma as the delimiter between disabled default blocked parameters." 16 | }, 17 | "blocked_params": { 18 | "message": "拦截参数" 19 | }, 20 | "blocked_params_descr": { 21 | "message": "从网址中移除的参数,大小写敏感。拦截特定域名的参数可用例如 param@domain.com。使用逗号分隔多个参数。

Parameter rules" 22 | }, 23 | "icon_animation": { 24 | "message": "图标动画" 25 | }, 26 | "icon_animation_descr": { 27 | "message": "Neat URL 清理网址时呈现的动画。" 28 | }, 29 | "icon_animation_none": { 30 | "message": "无动画" 31 | }, 32 | "icon_animation_missing_underscore": { 33 | "message": "下划线消失" 34 | }, 35 | "icon_animation_rotate": { 36 | "message": "图标旋转" 37 | }, 38 | "icon_animation_surprise_me": { 39 | "message": "随机动画" 40 | }, 41 | "icon_theme": { 42 | "message": "图标主题" 43 | }, 44 | "icon_theme_descr": { 45 | "message": "默认使用暗色图标。您可以更改此选项以使用明亮图标。" 46 | }, 47 | "icon_theme_dark": { 48 | "message": "始终使用暗色图标" 49 | }, 50 | "icon_theme_light": { 51 | "message": "始终使用明亮图标" 52 | }, 53 | "icon_theme_dark_notiflight": { 54 | "message": "使用暗色图标(通知除外)" 55 | }, 56 | "icon_theme_light_notifdark": { 57 | "message": "使用明亮图标(通知除外)" 58 | }, 59 | "show_counter": { 60 | "message": "Show counter" 61 | }, 62 | "show_counter_descr": { 63 | "message": "Show a counter which displays the number of rewritten URLs." 64 | }, 65 | "counter_background_color": { 66 | "message": "Counter background color" 67 | }, 68 | "counter_background_color_descr": { 69 | "message": "The background color used by the counter." 70 | }, 71 | "enable_logging": { 72 | "message": "启用日志" 73 | }, 74 | "enable_logging_descr": { 75 | "message": "将网址变更记录到浏览器控制台。" 76 | }, 77 | "advanced": { 78 | "message": "高级" 79 | }, 80 | "advanced_descr": { 81 | "message": "慎重修改,以防故障。" 82 | }, 83 | "theme": { 84 | "message": "Theme" 85 | }, 86 | "theme_descr": { 87 | "message": "Icon and notification theme options." 88 | }, 89 | "blacklist": { 90 | "message": "Domain blacklist" 91 | }, 92 | "blacklist_descr": { 93 | "message": "Comma separated list of domains. Neat URL will not work on these websites." 94 | }, 95 | "url_request_types": { 96 | "message": "网址请求类型" 97 | }, 98 | "url_request_types_descr": { 99 | "message": "默认值:main_frame。此列表以逗号分隔。有效值见资源类型列表。", 100 | "description": "Please leave the link intact. You can translate the normal text and the text 'the list of resource types'. The link must not be changed. main_frame must also stay the same." 101 | }, 102 | "counter_default_color": { 103 | "message": "Use the default counter color" 104 | }, 105 | "savepreferences": { 106 | "message": "保存设置" 107 | }, 108 | "notify_preferences_saved": { 109 | "message": "设置已保存" 110 | }, 111 | "change_links_in_page": { 112 | "message": "Change links in page" 113 | }, 114 | "change_links_in_page_descr": { 115 | "message": "Remove blocked parameters from all links when loading a page" 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Sources: 2 | // * First version from Pure URL 3 | // * https://cheeky4n6monkey.blogspot.nl/2014/10/google-eid.html 4 | // * https://greasyfork.org/en/scripts/10096-general-url-cleaner 5 | // * https://webapps.stackexchange.com/questions/9863/are-the-parameters-for-www-youtube-com-watch-documented 6 | // * https://github.com/Smile4ever/firefoxaddons/issues/25 7 | // * https://github.com/Smile4ever/firefoxaddons/issues/43 8 | 9 | /// Runtime setting 10 | let enabled = true; 11 | 12 | /// Used by addons.mozilla.org handling 13 | let globalNeatURL = ""; 14 | let globalCurrentURL = ""; 15 | let globalTabId = -1; 16 | 17 | /// Badge and browserAction (the variable version is also used for upgrades) 18 | let badge = []; // Hold the badge counts 19 | let version = browser.runtime.getManifest().version; 20 | 21 | /// Preferences from JSON 22 | let neat_url_default_blocked_params; // Exception: this is not editable and doesn't come out of storage local! 23 | 24 | /// Preferences 25 | let neat_url_icon_animation; // none, missing_underscore, rotate or surprise_me 26 | let neat_url_icon_theme; 27 | let neat_url_counter_color; 28 | let neat_url_counter_default_color; 29 | let neat_url_blocked_params; 30 | 31 | let neat_url_types; // Used to init the onBeforeRequest listener 32 | let neat_url_version; // Used for upgrading purposes: previous version when upgrading, after upgrading the current version 33 | 34 | async function init(){ 35 | let storageLocalResult = await browser.storage.local.get([ 36 | "neat_url_icon_animation", 37 | "neat_url_icon_theme", 38 | "neat_url_counter_color", 39 | "neat_url_counter_default_color", 40 | "neat_url_blocked_params", 41 | "neat_url_types", 42 | "neat_url_version" 43 | ]); 44 | 45 | neat_url_icon_animation = valueOrDefault(storageLocalResult.neat_url_icon_animation, "missing_underscore"); 46 | neat_url_icon_theme = valueOrDefault(storageLocalResult.neat_url_icon_theme, "dark"); 47 | neat_url_counter_color = valueOrDefault(storageLocalResult.neat_url_counter_color, "#000000"); 48 | neat_url_counter_default_color = valueOrDefault(storageLocalResult.neat_url_counter_default_color, true); // true as default 49 | 50 | neat_url_blocked_params = valueOrDefaultArray(storageLocalResult.neat_url_blocked_params, []); 51 | neat_url_types = valueOrDefaultArray(storageLocalResult.neat_url_types, defaultRequestResourceTypes); 52 | neat_url_version = valueOrDefault(storageLocalResult.neat_url_version, "0.1.0"); 53 | 54 | // Upgrade configuration from old releases 55 | if(neat_url_counter_default_color == null && neat_url_counter_color == "#eeeeee"){ 56 | // Update counter_color to null 57 | browser.storage.local.set({ neat_url_counter_color: null }); 58 | 59 | // Update counter_default_color to true 60 | browser.storage.local.set({ neat_url_counter_default_color: true }); // not strictly needed, but this shouldn't hurt either 61 | 62 | // Do not use any color 63 | neat_url_counter_default_color = true; 64 | } 65 | 66 | if(!neat_url_counter_default_color) 67 | browser.browserAction.setBadgeBackgroundColor({color: neat_url_counter_color}); 68 | 69 | // Re-initialise listener, hopefully fixes https://github.com/Smile4ever/firefoxaddons/issues/92 70 | browser.webRequest.onBeforeRequest.removeListener(cleanURL); 71 | if(neat_url_types.length != 0){ 72 | /// Register for types specified in neat_url_types 73 | browser.webRequest.onBeforeRequest.addListener( 74 | cleanURL, 75 | {urls: [""], types: neat_url_types}, 76 | ["blocking"] 77 | ); 78 | } 79 | 80 | initBrowserAction(); // needs neat_url_icon_theme 81 | initCounter(); // needs neat_url_show_counter 82 | deleteDefaultParametersFromBlockedParameters(); // needs neat_url_icon_theme / neat_url_blocked_params / neat_url_override_default_blocked_params 83 | 84 | initContextMenus(); 85 | } 86 | init(); 87 | 88 | ///Messages 89 | // listen for messages from the content or options script 90 | browser.runtime.onMessage.addListener((message) => { 91 | switch (message.action) { 92 | case "refresh-options": 93 | init(); 94 | break; 95 | case "notify": 96 | notify(message.data); 97 | break; 98 | case "incrementBadgeValue": 99 | incrementBadgeValue(message.data); 100 | break; 101 | case "animateToolbarIcon": 102 | animateToolbarIcon(); 103 | break; 104 | default: 105 | break; 106 | } 107 | }); 108 | 109 | /// Browser action 110 | /// Neat URL code 111 | function initBrowserAction(){ 112 | browser.browserAction.setIcon({path: resolveIconURL("neaturl-96-state0.png")}); 113 | browser.browserAction.setTitle({title: "Neat URL " + version + " - enabled"}); 114 | 115 | browser.browserAction.onClicked.addListener(async (tab) => { 116 | enabled = !enabled; 117 | if(enabled) notify("Neat URL is now enabled", "state"); 118 | if(!enabled) notify("Neat URL is now disabled", "state"); 119 | 120 | await browser.storage.local.set({ enabled: enabled }); 121 | sendMessage("refresh-options", enabled); 122 | enabled_2 = enabled; // shared.js loaded as background script 123 | 124 | updateIcon(); 125 | }); 126 | } 127 | 128 | /// Context menus 129 | function initContextMenus(){ 130 | browser.contextMenus.onClicked.removeListener(listener); 131 | browser.contextMenus.removeAll().catch(null); 132 | 133 | createContextMenu("neaturl-tb-preferences", "Preferences", ["browser_action"]); 134 | browser.contextMenus.onClicked.addListener(listener); 135 | } 136 | 137 | function createContextMenu(id, title, contexts){ 138 | browser.contextMenus.create({ 139 | id: id, 140 | title: title, 141 | contexts: contexts 142 | }); 143 | } 144 | 145 | function listener(info, tab){ 146 | if(info.menuItemId == "neaturl-tb-preferences"){ 147 | browser.runtime.openOptionsPage(); 148 | return; 149 | } 150 | } 151 | 152 | /// Neat URL code 153 | function deleteDefaultParametersFromBlockedParameters(){ 154 | // Delete all parameters from the user storage that are already contained in the default parameters 155 | // The default parameters will be editable, but only the offset will be saved 156 | // That makes future updates easier 157 | 158 | let oldVersion = neat_url_version; 159 | let newVersion = browser.runtime.getManifest().version; 160 | // Upgrade value in browser.storage.local if oldVersion != newVersion 161 | oldVersion = "1.0.0"; 162 | if(oldVersion != newVersion){ 163 | let changes = false; 164 | let defaultParams = neat_url_default_blocked_params; 165 | 166 | for(let defaultParam of defaultParams){ 167 | if(defaultParam.endsWith("_*")){ 168 | let paramToFind = defaultParam.replace("_*", "_"); 169 | let lengthBefore = neat_url_blocked_params.length; 170 | neat_url_blocked_params = neat_url_blocked_params.filter((blocked) => !blocked.startsWith(paramToFind)); 171 | let lengthAfter = neat_url_blocked_params.length; 172 | 173 | if(lengthAfter != lengthBefore){ 174 | changes = true; 175 | } 176 | } 177 | 178 | if(neat_url_blocked_params.includes(defaultParam)){ 179 | neat_url_blocked_params = removeFromArray(neat_url_blocked_params, defaultParam); 180 | changes = true; 181 | } 182 | } 183 | 184 | if(changes){ 185 | browser.storage.local.set({"neat_url_blocked_params": neat_url_blocked_params.join(', ')}) 186 | } 187 | 188 | browser.storage.local.set({"neat_url_version": newVersion}); 189 | } 190 | } 191 | 192 | function notify(message, id){ 193 | if(typeof id == undefined) id = message.substring(0, 20) 194 | browser.notifications.create(id, 195 | { 196 | type: "basic", 197 | iconUrl: browser.runtime.getURL(resolveIconUrlNotif("neaturl-96-state0.png")), 198 | title: "Neat URL", 199 | message: message 200 | }); 201 | } 202 | -------------------------------------------------------------------------------- /browser-polyfill.min.js: -------------------------------------------------------------------------------- 1 | (function(a,b){if("function"==typeof define&&define.amd)define("webextension-polyfill",["module"],b);else if("undefined"!=typeof exports)b(module);else{var c={exports:{}};b(c),a.browser=c.exports}})("undefined"==typeof globalThis?"undefined"==typeof self?this:self:globalThis,function(a){"use strict";if("undefined"==typeof browser||Object.getPrototypeOf(browser)!==Object.prototype){if("object"!=typeof chrome||!chrome||!chrome.runtime||!chrome.runtime.id)throw new Error("This script should only be loaded in a browser extension.");a.exports=(a=>{const b={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(0===Object.keys(b).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class c extends WeakMap{constructor(a,b=void 0){super(b),this.createItem=a}get(a){return this.has(a)||this.set(a,this.createItem(a)),super.get(a)}}const d=a=>a&&"object"==typeof a&&"function"==typeof a.then,e=(b,c)=>(...d)=>{a.runtime.lastError?b.reject(a.runtime.lastError):c.singleCallbackArg||1>=d.length&&!1!==c.singleCallbackArg?b.resolve(d[0]):b.resolve(d)},f=a=>1==a?"argument":"arguments",g=(a,b)=>function(c,...d){if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((f,g)=>{if(b.fallbackToNoCallback)try{c[a](...d,e({resolve:f,reject:g},b))}catch(e){console.warn(`${a} API method doesn't seem to support the callback parameter, `+"falling back to call it without a callback: ",e),c[a](...d),b.fallbackToNoCallback=!1,b.noCallback=!0,f()}else b.noCallback?(c[a](...d),f()):c[a](...d,e({resolve:f,reject:g},b))})},h=(a,b,c)=>new Proxy(b,{apply(b,d,e){return c.call(d,a,...e)}});let i=Function.call.bind(Object.prototype.hasOwnProperty);const j=(a,b={},c={})=>{let d=Object.create(null),e={has(b,c){return c in a||c in d},get(e,f){if(f in d)return d[f];if(!(f in a))return;let k=a[f];if("function"==typeof k){if("function"==typeof b[f])k=h(a,a[f],b[f]);else if(i(c,f)){let b=g(f,c[f]);k=h(a,a[f],b)}else k=k.bind(a);}else if("object"==typeof k&&null!==k&&(i(b,f)||i(c,f)))k=j(k,b[f],c[f]);else if(i(c,"*"))k=j(k,b[f],c["*"]);else return Object.defineProperty(d,f,{configurable:!0,enumerable:!0,get(){return a[f]},set(b){a[f]=b}}),k;return d[f]=k,k},set(b,c,e){return c in d?d[c]=e:a[c]=e,!0},defineProperty(a,b,c){return Reflect.defineProperty(d,b,c)},deleteProperty(a,b){return Reflect.deleteProperty(d,b)}},f=Object.create(a);return new Proxy(f,e)},k=a=>({addListener(b,c,...d){b.addListener(a.get(c),...d)},hasListener(b,c){return b.hasListener(a.get(c))},removeListener(b,c){b.removeListener(a.get(c))}});let l=!1;const m=new c(a=>"function"==typeof a?function(b,c,e){let f,g,h=!1,i=new Promise(a=>{f=function(b){l||(console.warn("Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)",new Error().stack),l=!0),h=!0,a(b)}});try{g=a(b,c,f)}catch(a){g=Promise.reject(a)}const j=!0!==g&&d(g);if(!0!==g&&!j&&!h)return!1;const k=a=>{a.then(a=>{e(a)},a=>{let b;b=a&&(a instanceof Error||"string"==typeof a.message)?a.message:"An unexpected error occurred",e({__mozWebExtensionPolyfillReject__:!0,message:b})}).catch(a=>{console.error("Failed to send onMessage rejected reply",a)})};return j?k(g):k(i),!0}:a),n=({reject:b,resolve:c},d)=>{a.runtime.lastError?a.runtime.lastError.message==="The message port closed before a response was received."?c():b(a.runtime.lastError):d&&d.__mozWebExtensionPolyfillReject__?b(new Error(d.message)):c(d)},o=(a,b,c,...d)=>{if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((a,b)=>{const e=n.bind(null,{resolve:a,reject:b});d.push(e),c.sendMessage(...d)})},p={runtime:{onMessage:k(m),onMessageExternal:k(m),sendMessage:o.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:o.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},q={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return b.privacy={network:{"*":q},services:{"*":q},websites:{"*":q}},j(a,p,b)})(chrome)}else a.exports=browser}); 2 | //# sourceMappingURL=browser-polyfill.min.js.map 3 | 4 | // webextension-polyfill v.0.6.0 (https://github.com/mozilla/webextension-polyfill) 5 | 6 | /* This Source Code Form is subject to the terms of the Mozilla Public 7 | * License, v. 2.0. If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 9 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | NEATURLVERSION=$(jq -r '.version' manifest.json) 3 | echo "Building Neat URL $NEATURLVERSION" 4 | echo "Requirements:" 5 | echo "- jq" 6 | echo "- git" 7 | echo "- web-ext" 8 | echo "- npm" 9 | 10 | #Execute this in a sudo or administrator terminal 11 | #npm install --global web-ext 12 | 13 | if [ ! -f "browser-polyfill.min.js" ] || [ $(find "browser-polyfill.min.js" -mtime +0) ]; then 14 | echo "Downloading browser-polyfill.min.js" 15 | git clone https://github.com/mozilla/webextension-polyfill polyfill 16 | cd polyfill 17 | npm install 18 | npm run build 19 | npm run test 20 | cp dist/browser-polyfill.min.js ../browser-polyfill.min.js 21 | cd .. 22 | rm -rf polyfill 23 | fi 24 | 25 | echo "Deleting old build directory" 26 | rm -rf build 2>/dev/null 27 | echo "Deleting node_modules directory" 28 | rm -rf node_modules 2>/dev/null 29 | 30 | # Build ZIP - Chrome 31 | echo "Copying files for Chrome" 32 | mkdir build 33 | shopt -s extglob # to enable extglob 34 | cp -r !(build*) build/ 35 | 36 | cd build 37 | rm -rf web-ext-artifacts 38 | rm package.json 39 | rm package-lock.json 40 | jq -r 'del(.applications) | del(.browser_action.browser_style) | del(.options_ui.browser_style)' manifest.json > manifest-chrome.json #Chrome 41 | rm manifest.json #Chrome 42 | mv manifest-chrome.json manifest.json #Chrome 43 | 44 | echo "Building ZIP for Chrome.." 45 | web-ext build --ignore-files build.sh images *.md *.txt .gitignore --filename "{name}-{version}.chrome.zip" 46 | 47 | cd .. 48 | yes | cp build/web-ext-artifacts/* web-ext-artifacts/ 49 | 50 | rm -rf build 51 | 52 | # Build ZIP - Firefox 53 | echo "" 54 | echo "Copying files for Firefox" 55 | mkdir build 56 | shopt -s extglob # to enable extglob 57 | cp -r !(build*) build/ #copy all files in current directory to build except for the directory build 58 | 59 | cd build 60 | rm -rf web-ext-artifacts 61 | rm package.json 62 | rm package-lock.json 63 | rm browser-polyfill.min.js 64 | touch browser-polyfill.min.js 65 | 66 | echo "Building ZIP for Firefox.." 67 | web-ext build --ignore-files build.sh images *.md *.txt .gitignore --filename "{name}-{version}.firefox.zip" 68 | 69 | cd .. 70 | yes | cp build/web-ext-artifacts/* web-ext-artifacts/ 71 | 72 | rm -rf build 73 | 74 | echo "" 75 | echo "Done building Neat URL $NEATURLVERSION:" 76 | #find web-ext-artifacts -mmin -1 -type f -print 77 | cd web-ext-artifacts 78 | ls -t | head -n2 -------------------------------------------------------------------------------- /css/options.chrome.css: -------------------------------------------------------------------------------- 1 | body { 2 | min-width: 1200px; 3 | max-width: 100%; 4 | padding: 50px; 5 | } 6 | 7 | #optionsform{ 8 | margin-top: -50px; 9 | } 10 | 11 | .flexbox-container > div { 12 | padding-top: 10px; 13 | padding-bottom: 10px; 14 | } 15 | 16 | .firsthr{ 17 | display: none; 18 | } -------------------------------------------------------------------------------- /css/options.css: -------------------------------------------------------------------------------- 1 | /* Used from https://stackoverflow.com/questions/306252/how-to-align-checkboxes-and-their-labels-consistently-cross-browsers */ 2 | .labelbox label { 3 | display: block; 4 | padding-left: 15px; 5 | text-indent: -15px; 6 | } 7 | 8 | input[type=checkbox] { 9 | width: 13px; 10 | height: 13px; 11 | padding: 0; 12 | margin:0; 13 | margin-right: 3px; 14 | vertical-align: bottom; 15 | position: relative; 16 | top: -1px; 17 | *overflow: hidden; 18 | } 19 | /* End of used CSS */ 20 | 21 | input[type=number]{ 22 | max-width: 4em; 23 | } 24 | 25 | body{ 26 | box-sizing: border-box; 27 | } 28 | 29 | /* CSS used from https://github.com/kainsavage/HistoryBlock/blob/web-extension/options/options.css */ 30 | body, button, input, textarea { 31 | /*font-family: Segoe UI, sans-serif;*/ 32 | font-size: 14px; 33 | } 34 | 35 | body, button{ 36 | color: #333; /* From Mozilla Firefox CSS */ 37 | } 38 | 39 | button { 40 | padding: 4px 20px; 41 | background-color: #fbfbfb; 42 | border: 1px solid #bbb; 43 | border-radius: 2px; /* From Mozilla Firefox CSS */ 44 | margin: 0 4px; 45 | } 46 | 47 | button:hover { 48 | background-color: #ebebeb; 49 | } 50 | /* End of used CSS */ 51 | 52 | .descr{ 53 | margin-inline-start: 1em; 54 | -moz-box-align: center; 55 | font-size: 0.85em; 56 | /* font-size: 1.25rem; */ 57 | color: gray; 58 | } 59 | 60 | .hr{ 61 | border-bottom: 1px solid #bbb 62 | } 63 | .firefox .firsthr{ 64 | display: block; 65 | } 66 | 67 | /* CSS used from https://davidwalsh.name/flexbox-column */ 68 | .flexbox-container { 69 | display: -ms-flex; 70 | display: -webkit-flex; 71 | display: flex; 72 | } 73 | 74 | .flexbox-container > div { 75 | width: 33%; 76 | } 77 | 78 | .flexbox-container > div:first-child { 79 | margin-right: 20px; 80 | } 81 | /* End of used CSS */ 82 | 83 | button::-moz-focus-inner { 84 | border: 0; 85 | } 86 | /*.labelbox{ 87 | min-width: 350px; 88 | }*/ 89 | -------------------------------------------------------------------------------- /css/options.firefox.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin:0; 3 | padding:0; 4 | } 5 | 6 | .flexbox-container > div { 7 | padding-top: 10px; 8 | padding-bottom: 10px; 9 | } 10 | 11 | .description{ 12 | display: none; 13 | } 14 | -------------------------------------------------------------------------------- /data/default-params-by-category.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { "name": "Action Map", "params": ["action_object_map", "action_ref_map", "action_type_map"]}, 4 | { "name": "AliExpress.com", "params": ["aff_platform", "aff_trace_key", "algo_expid@*.aliexpress.*", "algo_pvid@*.aliexpress.com", "btsid@*.aliexpress.com", "expid@*.aliexpress.com", "initiative_id@*.aliexpress.com", "scm_id@*.aliexpress.com", "spm@*.aliexpress.com", "ws_ab_test*.aliexpress.com"]}, 5 | { "name": "Amazon", "params": ["_encoding@amazon.*", "ascsubtag@amazon.*", "pd_rd_*@amazon.*", "pf@amazon.*", "pf_rd_*@amazon.*", "psc@amazon.*", "ref_@amazon.*", "tag@amazon.*"]}, 6 | { "name": "Bilibili.com", "params": ["callback@bilibili.com"]}, 7 | { "name": "Bing", "params": ["cvid@bing.com", "form@bing.com", "pq@bing.com", "qs@bing.com", "sc@bing.com", "sk@bing.com", "sp@bing.com"]}, 8 | { "name": "Campaign tracking (Adobe Analytics)", "params": ["sc_cid"]}, 9 | { "name": "Campaign tracking (Adobe Marketo)", "params": ["mkt_tok"]}, 10 | { "name": "Campaign tracking (Amazon Kendra)", "params": ["trk", "trkCampaign"]}, 11 | { "name": "Campaign tracking (at)", "params": ["at_campaign", "at_custom*", "at_medium"]}, 12 | { "name": "Campaign tracking (Change.org)", "params": ["guest@change.org", "recruited_by_id@change.org", "recruiter@change.org", "short_display_name@change.org", "source_location@change.org"]}, 13 | { "name": "Campaign tracking (DPG Media)", "params": ["dpg_*"]}, 14 | { "name": "Campaign tracking (Google Analytics, ga)", "params": ["ga_*", "gclid", "gclsrc"]}, 15 | { "name": "Campaign tracking (Humble Bundle)", "params": ["hmb_campaign", "hmb_medium", "hmb_source"]}, 16 | { "name": "Campaign tracking (IBM Acoustic Campaign)", "params": ["spJobID", "spMailingID", "spReportId", "spUserID"]}, 17 | { "name": "Campaign tracking (itm)", "params": ["itm_*"], "docs": "https://www.parse.ly/help/post/4843/campaign-data-tracking/"}, 18 | { "name": "Campaign tracking (Omniture)", "params": ["s_cid"], "docs": "https://moz.com/community/q/omniture-tracking-code-urls-creating-duplicate-content"}, 19 | { "name": "Campaign tracking (Oracle Eloqua)", "params": ["assetId", "assetType", "campaignId", "elqTrack", "elqTrackId", "recipientId", "siteId"]}, 20 | { "name": "Campaign tracking (MailChimp)", "params": ["mc_cid", "mc_eid"], "docs": "https://www.learndigitaladvertising.com/solved-why-how-to-remove-mc_cid-and-mc_eid-from-google-analytics/"}, 21 | { "name": "Campaign tracking (Matomo/Piwik)", "params": ["mtm_*", "pk_*"]}, 22 | { "name": "Campaign tracking (ns)", "params": ["ns_*"]}, 23 | { "name": "Campaign tracking (sc)", "params": ["sc_campaign", "sc_channel", "sc_content", "sc_country", "sc_geo", "sc_medium", "sc_outcome"]}, 24 | { "name": "Campaign tracking (stm)", "params": ["stm_*"]}, 25 | { "name": "Campaign tracking (utm)", "params": ["nr_email_referer", "utm_*"]}, 26 | { "name": "Campaign tracking (Vero)", "params": ["vero_conv", "vero_id"], "docs": "https://help.getvero.com/articles/conversion-tracking.html"}, 27 | { "name": "Campaign tracking (Yandex)", "params": ["_openstat", "yclid"], "docs": "https://yandex.com/support/direct/statistics/url-tags.html"}, 28 | { "name": "Campaign tracking (others)", "params": ["c_id", "campaign_id", "Campaign", "cmpid", "mbid", "ncid"], "docs": "https://www.parse.ly/help/post/4843/campaign-data-tracking/"}, 29 | { "name": "Caseking.de", "params": ["campaign@caseking.de", "sPartner@caseking.de"]}, 30 | { "name": "Ebay", "params": ["_trkparms@ebay.*", "_trksid@ebay.*", "amdata@ebay.*", "epid@ebay.*", "hash@ebay.*", "var@ebay.*"]}, 31 | { "name": "Etsy", "params": ["click_key@etsy.com", "click_sum@etsy.com", "organic_search_click@etsy.com", "ref@etsy.com"]}, 32 | { "name": "Facebook", "params": ["fb_action_ids", "fb_action_types", "fb_ref", "fb_source", "fbclid", "hrc@facebook.com", "refsrc@facebook.com"]}, 33 | { "name": "Google", "params": ["ei@google.*", "gs_gbg@google.*", "gs_l", "gs_lcp@google.*", "gs_mss@google.*", "gs_rn@google.*", "gws_rd@google.*", "sei@google.*", "ved@google.*"]}, 34 | { "name": "Hubspot", "params": ["_hsenc", "_hsmi", "__hssc", "__hstc", "hsCtaTracking"]}, 35 | { "name": "IMDb", "params": ["pf_rd_*@imdb.com", "ref_@imdb.com"]}, 36 | { "name": "LinkedIn", "params": ["eBP@linkedin.com", "lgCta@linkedin.com", "lgTemp@linkedin.com", "lipi@linkedin.com", "midSig@linkedin.com", "midToken@linkedin.com", "recommendedFlavor@linkedin.com", "refId@linkedin.com", "trackingId@linkedin.com", "trk@linkedin.com", "trkEmail@linkedin.com"]}, 37 | { "name": "Medium", "params": ["_branch_match_id@medium.com", "source@medium.com"]}, 38 | { "name": "SourceForge.net", "params": ["position@sourceforge.net", "source@sourceforge.net"]}, 39 | { "name": "Spotify", "params": ["context@open.spotify.com", "si@open.spotify.com"]}, 40 | { "name": "TikTok", "params": ["_d@tiktok.com", "checksum@tiktok.com", "is_copy_url@tiktok.com", "is_from_webapp@tiktok.com", "language@tiktok.com", "preview_pb@tiktok.com", "sec_user_id@tiktok.com", "sender_device@tiktok.com", "sender_web_id@tiktok.com", "share_app_id@tiktok.com", "share_link_id@tiktok.com", "share_item_id@tiktok.com", "source@tiktok.com", "timestamp@tiktok.com", "tt_from@tiktok.com", "u_code@tiktok.com", "user_id@tiktok.com"]}, 41 | { "name": "Twitch.tv", "params": ["tt_content", "tt_medium"]}, 42 | { "name": "Twitter", "params": ["cxt@*.twitter.com", "ref_*@*.twitter.com", "s@*.twitter.com", "t@*.twitter.com", "twclid"]}, 43 | { "name": "Yahoo", "params": ["guccounter@*.yahoo.com", "soc_src", "soc_trk"]}, 44 | { "name": "Yandex", "params": ["lr@yandex.*", "redircnt@yandex.*"]}, 45 | { "name": "YouTube.com", "params": ["feature@youtube.com", "kw@youtube.com"]}, 46 | { "name": "Zeit.de", "params": ["wt_mc", "wt_zmc"]} 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /data/publicsuffix-ccSLD.txt: -------------------------------------------------------------------------------- 1 | com.ac 2 | edu.ac 3 | gov.ac 4 | net.ac 5 | mil.ac 6 | org.ac 7 | nom.ad 8 | co.ae 9 | net.ae 10 | org.ae 11 | sch.ae 12 | ac.ae 13 | gov.ae 14 | mil.ae 15 | gov.af 16 | com.af 17 | org.af 18 | net.af 19 | edu.af 20 | com.ag 21 | org.ag 22 | net.ag 23 | co.ag 24 | nom.ag 25 | off.ai 26 | com.ai 27 | net.ai 28 | org.ai 29 | com.al 30 | edu.al 31 | gov.al 32 | mil.al 33 | net.al 34 | org.al 35 | ed.ao 36 | gv.ao 37 | og.ao 38 | co.ao 39 | pb.ao 40 | it.ao 41 | com.ar 42 | edu.ar 43 | gob.ar 44 | gov.ar 45 | int.ar 46 | mil.ar 47 | net.ar 48 | org.ar 49 | tur.ar 50 | gov.as 51 | ac.at 52 | co.at 53 | gv.at 54 | or.at 55 | com.au 56 | net.au 57 | org.au 58 | edu.au 59 | gov.au 60 | asn.au 61 | id.au 62 | oz.au 63 | act.au 64 | nsw.au 65 | nt.au 66 | qld.au 67 | sa.au 68 | tas.au 69 | vic.au 70 | wa.au 71 | com.aw 72 | com.az 73 | net.az 74 | int.az 75 | gov.az 76 | org.az 77 | edu.az 78 | pp.az 79 | mil.az 80 | pro.az 81 | biz.az 82 | com.ba 83 | edu.ba 84 | gov.ba 85 | mil.ba 86 | net.ba 87 | org.ba 88 | biz.bb 89 | co.bb 90 | com.bb 91 | edu.bb 92 | gov.bb 93 | net.bb 94 | org.bb 95 | tv.bb 96 | ac.be 97 | gov.bf 98 | com.bh 99 | edu.bh 100 | net.bh 101 | org.bh 102 | gov.bh 103 | co.bi 104 | com.bi 105 | edu.bi 106 | or.bi 107 | org.bi 108 | com.bm 109 | edu.bm 110 | gov.bm 111 | net.bm 112 | org.bm 113 | com.bo 114 | edu.bo 115 | gob.bo 116 | int.bo 117 | org.bo 118 | net.bo 119 | mil.bo 120 | tv.bo 121 | web.bo 122 | abc.br 123 | adm.br 124 | adv.br 125 | agr.br 126 | aju.br 127 | am.br 128 | arq.br 129 | art.br 130 | ato.br 131 | bhz.br 132 | bio.br 133 | bmd.br 134 | bsb.br 135 | cim.br 136 | cng.br 137 | cnt.br 138 | com.br 139 | cri.br 140 | def.br 141 | ecn.br 142 | eco.br 143 | edu.br 144 | emp.br 145 | eng.br 146 | esp.br 147 | etc.br 148 | eti.br 149 | far.br 150 | fm.br 151 | fnd.br 152 | fot.br 153 | foz.br 154 | fst.br 155 | ggf.br 156 | gov.br 157 | gru.br 158 | imb.br 159 | ind.br 160 | inf.br 161 | jab.br 162 | jdf.br 163 | jor.br 164 | jus.br 165 | leg.br 166 | lel.br 167 | mat.br 168 | med.br 169 | mil.br 170 | mp.br 171 | mus.br 172 | net.br 173 | not.br 174 | ntr.br 175 | odo.br 176 | org.br 177 | poa.br 178 | ppg.br 179 | pro.br 180 | psc.br 181 | psi.br 182 | pvh.br 183 | qsl.br 184 | rec.br 185 | rio.br 186 | sjc.br 187 | slg.br 188 | slz.br 189 | srv.br 190 | teo.br 191 | the.br 192 | tmp.br 193 | trd.br 194 | tur.br 195 | tv.br 196 | udi.br 197 | vet.br 198 | vix.br 199 | zlg.br 200 | com.bs 201 | net.bs 202 | org.bs 203 | edu.bs 204 | gov.bs 205 | com.bt 206 | edu.bt 207 | gov.bt 208 | net.bt 209 | org.bt 210 | co.bw 211 | org.bw 212 | gov.by 213 | mil.by 214 | com.by 215 | of.by 216 | com.bz 217 | net.bz 218 | org.bz 219 | edu.bz 220 | gov.bz 221 | ab.ca 222 | bc.ca 223 | mb.ca 224 | nb.ca 225 | nf.ca 226 | nl.ca 227 | ns.ca 228 | nt.ca 229 | nu.ca 230 | on.ca 231 | pe.ca 232 | qc.ca 233 | sk.ca 234 | yk.ca 235 | gc.ca 236 | gov.cd 237 | org.ci 238 | or.ci 239 | com.ci 240 | co.ci 241 | edu.ci 242 | ed.ci 243 | ac.ci 244 | net.ci 245 | go.ci 246 | int.ci 247 | md.ci 248 | gov.cl 249 | gob.cl 250 | co.cl 251 | mil.cl 252 | co.cm 253 | com.cm 254 | gov.cm 255 | net.cm 256 | ac.cn 257 | com.cn 258 | edu.cn 259 | gov.cn 260 | net.cn 261 | org.cn 262 | mil.cn 263 | ah.cn 264 | bj.cn 265 | cq.cn 266 | fj.cn 267 | gd.cn 268 | gs.cn 269 | gz.cn 270 | gx.cn 271 | ha.cn 272 | hb.cn 273 | he.cn 274 | hi.cn 275 | hl.cn 276 | hn.cn 277 | jl.cn 278 | js.cn 279 | jx.cn 280 | ln.cn 281 | nm.cn 282 | nx.cn 283 | qh.cn 284 | sc.cn 285 | sd.cn 286 | sh.cn 287 | sn.cn 288 | sx.cn 289 | tj.cn 290 | xj.cn 291 | xz.cn 292 | yn.cn 293 | zj.cn 294 | hk.cn 295 | mo.cn 296 | tw.cn 297 | com.co 298 | edu.co 299 | gov.co 300 | int.co 301 | mil.co 302 | net.co 303 | nom.co 304 | org.co 305 | rec.co 306 | web.co 307 | ac.cr 308 | co.cr 309 | ed.cr 310 | fi.cr 311 | go.cr 312 | or.cr 313 | sa.cr 314 | com.cu 315 | edu.cu 316 | org.cu 317 | net.cu 318 | gov.cu 319 | inf.cu 320 | com.cw 321 | edu.cw 322 | net.cw 323 | org.cw 324 | gov.cx 325 | ac.cy 326 | biz.cy 327 | com.cy 328 | gov.cy 329 | ltd.cy 330 | net.cy 331 | org.cy 332 | pro.cy 333 | tm.cy 334 | com.dm 335 | net.dm 336 | org.dm 337 | edu.dm 338 | gov.dm 339 | art.do 340 | com.do 341 | edu.do 342 | gob.do 343 | gov.do 344 | mil.do 345 | net.do 346 | org.do 347 | sld.do 348 | web.do 349 | com.dz 350 | org.dz 351 | net.dz 352 | gov.dz 353 | edu.dz 354 | pol.dz 355 | art.dz 356 | com.ec 357 | net.ec 358 | fin.ec 359 | med.ec 360 | pro.ec 361 | org.ec 362 | edu.ec 363 | gov.ec 364 | gob.ec 365 | mil.ec 366 | edu.ee 367 | gov.ee 368 | lib.ee 369 | med.ee 370 | com.ee 371 | pri.ee 372 | aip.ee 373 | org.ee 374 | fie.ee 375 | com.eg 376 | edu.eg 377 | eun.eg 378 | gov.eg 379 | mil.eg 380 | net.eg 381 | org.eg 382 | sci.eg 383 | com.es 384 | nom.es 385 | org.es 386 | gob.es 387 | edu.es 388 | com.et 389 | gov.et 390 | org.et 391 | edu.et 392 | biz.et 393 | net.et 394 | com.fr 395 | nom.fr 396 | prd.fr 397 | tm.fr 398 | cci.fr 399 | com.ge 400 | edu.ge 401 | gov.ge 402 | org.ge 403 | mil.ge 404 | net.ge 405 | pvt.ge 406 | co.gg 407 | net.gg 408 | org.gg 409 | com.gh 410 | edu.gh 411 | gov.gh 412 | org.gh 413 | mil.gh 414 | com.gi 415 | ltd.gi 416 | gov.gi 417 | mod.gi 418 | edu.gi 419 | org.gi 420 | co.gl 421 | com.gl 422 | edu.gl 423 | net.gl 424 | org.gl 425 | ac.gn 426 | com.gn 427 | edu.gn 428 | gov.gn 429 | org.gn 430 | net.gn 431 | com.gp 432 | net.gp 433 | edu.gp 434 | org.gp 435 | com.gr 436 | edu.gr 437 | net.gr 438 | org.gr 439 | gov.gr 440 | com.gt 441 | edu.gt 442 | gob.gt 443 | ind.gt 444 | mil.gt 445 | net.gt 446 | org.gt 447 | com.gu 448 | edu.gu 449 | gov.gu 450 | net.gu 451 | org.gu 452 | web.gu 453 | co.gy 454 | com.gy 455 | edu.gy 456 | gov.gy 457 | net.gy 458 | org.gy 459 | com.hk 460 | edu.hk 461 | gov.hk 462 | idv.hk 463 | net.hk 464 | org.hk 465 | com.hn 466 | edu.hn 467 | org.hn 468 | net.hn 469 | mil.hn 470 | gob.hn 471 | iz.hr 472 | com.hr 473 | com.ht 474 | net.ht 475 | pro.ht 476 | org.ht 477 | med.ht 478 | art.ht 479 | pol.ht 480 | edu.ht 481 | rel.ht 482 | co.hu 483 | org.hu 484 | tm.hu 485 | sex.hu 486 | ac.id 487 | biz.id 488 | co.id 489 | go.id 490 | mil.id 491 | my.id 492 | net.id 493 | or.id 494 | sch.id 495 | web.id 496 | gov.ie 497 | ac.il 498 | co.il 499 | gov.il 500 | idf.il 501 | net.il 502 | org.il 503 | ac.im 504 | co.im 505 | com.im 506 | net.im 507 | org.im 508 | tt.im 509 | tv.im 510 | co.in 511 | net.in 512 | org.in 513 | gen.in 514 | ind.in 515 | nic.in 516 | ac.in 517 | edu.in 518 | res.in 519 | gov.in 520 | mil.in 521 | eu.int 522 | com.io 523 | gov.iq 524 | edu.iq 525 | mil.iq 526 | com.iq 527 | org.iq 528 | net.iq 529 | ac.ir 530 | co.ir 531 | gov.ir 532 | id.ir 533 | net.ir 534 | org.ir 535 | sch.ir 536 | net.is 537 | com.is 538 | edu.is 539 | gov.is 540 | org.is 541 | int.is 542 | gov.it 543 | edu.it 544 | abr.it 545 | bas.it 546 | cal.it 547 | cam.it 548 | emr.it 549 | fvg.it 550 | laz.it 551 | lig.it 552 | lom.it 553 | mar.it 554 | mol.it 555 | pmn.it 556 | pug.it 557 | sar.it 558 | sic.it 559 | taa.it 560 | tos.it 561 | umb.it 562 | vao.it 563 | vda.it 564 | ven.it 565 | ag.it 566 | al.it 567 | an.it 568 | ao.it 569 | ap.it 570 | aq.it 571 | ar.it 572 | at.it 573 | av.it 574 | ba.it 575 | bg.it 576 | bi.it 577 | bl.it 578 | bn.it 579 | bo.it 580 | br.it 581 | bs.it 582 | bt.it 583 | bz.it 584 | ca.it 585 | cb.it 586 | ce.it 587 | ch.it 588 | ci.it 589 | cl.it 590 | cn.it 591 | co.it 592 | cr.it 593 | cs.it 594 | ct.it 595 | cz.it 596 | en.it 597 | fc.it 598 | fe.it 599 | fg.it 600 | fi.it 601 | fm.it 602 | fr.it 603 | ge.it 604 | go.it 605 | gr.it 606 | im.it 607 | is.it 608 | kr.it 609 | lc.it 610 | le.it 611 | li.it 612 | lo.it 613 | lt.it 614 | lu.it 615 | mb.it 616 | mc.it 617 | me.it 618 | mi.it 619 | mn.it 620 | mo.it 621 | ms.it 622 | mt.it 623 | na.it 624 | no.it 625 | nu.it 626 | og.it 627 | or.it 628 | ot.it 629 | pa.it 630 | pc.it 631 | pd.it 632 | pe.it 633 | pg.it 634 | pi.it 635 | pn.it 636 | po.it 637 | pr.it 638 | pt.it 639 | pu.it 640 | pv.it 641 | pz.it 642 | ra.it 643 | rc.it 644 | re.it 645 | rg.it 646 | ri.it 647 | rm.it 648 | rn.it 649 | ro.it 650 | sa.it 651 | si.it 652 | so.it 653 | sp.it 654 | sr.it 655 | ss.it 656 | sv.it 657 | ta.it 658 | te.it 659 | tn.it 660 | to.it 661 | tp.it 662 | tr.it 663 | ts.it 664 | tv.it 665 | ud.it 666 | va.it 667 | vb.it 668 | vc.it 669 | ve.it 670 | vi.it 671 | vr.it 672 | vs.it 673 | vt.it 674 | vv.it 675 | co.je 676 | net.je 677 | org.je 678 | com.jo 679 | org.jo 680 | net.jo 681 | edu.jo 682 | sch.jo 683 | gov.jo 684 | mil.jo 685 | ac.jp 686 | ad.jp 687 | co.jp 688 | ed.jp 689 | go.jp 690 | gr.jp 691 | lg.jp 692 | ne.jp 693 | or.jp 694 | mie.jp 695 | ac.ke 696 | co.ke 697 | go.ke 698 | me.ke 699 | ne.ke 700 | or.ke 701 | sc.ke 702 | org.kg 703 | net.kg 704 | com.kg 705 | edu.kg 706 | gov.kg 707 | mil.kg 708 | edu.ki 709 | biz.ki 710 | net.ki 711 | org.ki 712 | gov.ki 713 | com.ki 714 | org.km 715 | nom.km 716 | gov.km 717 | prd.km 718 | tm.km 719 | edu.km 720 | mil.km 721 | ass.km 722 | com.km 723 | net.kn 724 | org.kn 725 | edu.kn 726 | gov.kn 727 | com.kp 728 | edu.kp 729 | gov.kp 730 | org.kp 731 | rep.kp 732 | tra.kp 733 | ac.kr 734 | co.kr 735 | es.kr 736 | go.kr 737 | hs.kr 738 | kg.kr 739 | mil.kr 740 | ms.kr 741 | ne.kr 742 | or.kr 743 | pe.kr 744 | re.kr 745 | sc.kr 746 | edu.ky 747 | gov.ky 748 | com.ky 749 | org.ky 750 | net.ky 751 | org.kz 752 | edu.kz 753 | net.kz 754 | gov.kz 755 | mil.kz 756 | com.kz 757 | int.la 758 | net.la 759 | edu.la 760 | gov.la 761 | per.la 762 | com.la 763 | org.la 764 | com.lb 765 | edu.lb 766 | gov.lb 767 | net.lb 768 | org.lb 769 | com.lc 770 | net.lc 771 | co.lc 772 | org.lc 773 | edu.lc 774 | gov.lc 775 | gov.lk 776 | sch.lk 777 | net.lk 778 | int.lk 779 | com.lk 780 | org.lk 781 | edu.lk 782 | ngo.lk 783 | soc.lk 784 | web.lk 785 | ltd.lk 786 | grp.lk 787 | ac.lk 788 | com.lr 789 | edu.lr 790 | gov.lr 791 | org.lr 792 | net.lr 793 | co.ls 794 | org.ls 795 | gov.lt 796 | com.lv 797 | edu.lv 798 | gov.lv 799 | org.lv 800 | mil.lv 801 | id.lv 802 | net.lv 803 | asn.lv 804 | com.ly 805 | net.ly 806 | gov.ly 807 | plc.ly 808 | edu.ly 809 | sch.ly 810 | med.ly 811 | org.ly 812 | id.ly 813 | co.ma 814 | net.ma 815 | gov.ma 816 | org.ma 817 | ac.ma 818 | tm.mc 819 | co.me 820 | net.me 821 | org.me 822 | edu.me 823 | ac.me 824 | gov.me 825 | its.me 826 | org.mg 827 | nom.mg 828 | gov.mg 829 | prd.mg 830 | tm.mg 831 | edu.mg 832 | mil.mg 833 | com.mg 834 | co.mg 835 | com.mk 836 | org.mk 837 | net.mk 838 | edu.mk 839 | gov.mk 840 | inf.mk 841 | com.ml 842 | edu.ml 843 | gov.ml 844 | net.ml 845 | org.ml 846 | gov.mn 847 | edu.mn 848 | org.mn 849 | com.mo 850 | net.mo 851 | org.mo 852 | edu.mo 853 | gov.mo 854 | gov.mr 855 | com.ms 856 | edu.ms 857 | gov.ms 858 | net.ms 859 | org.ms 860 | com.mt 861 | edu.mt 862 | net.mt 863 | org.mt 864 | com.mu 865 | net.mu 866 | org.mu 867 | gov.mu 868 | ac.mu 869 | co.mu 870 | or.mu 871 | biz.mv 872 | com.mv 873 | edu.mv 874 | gov.mv 875 | int.mv 876 | mil.mv 877 | net.mv 878 | org.mv 879 | pro.mv 880 | ac.mw 881 | biz.mw 882 | co.mw 883 | com.mw 884 | edu.mw 885 | gov.mw 886 | int.mw 887 | net.mw 888 | org.mw 889 | com.mx 890 | org.mx 891 | gob.mx 892 | edu.mx 893 | net.mx 894 | com.my 895 | net.my 896 | org.my 897 | gov.my 898 | edu.my 899 | mil.my 900 | ac.mz 901 | adv.mz 902 | co.mz 903 | edu.mz 904 | gov.mz 905 | mil.mz 906 | net.mz 907 | org.mz 908 | pro.na 909 | or.na 910 | dr.na 911 | us.na 912 | mx.na 913 | ca.na 914 | in.na 915 | cc.na 916 | tv.na 917 | ws.na 918 | co.na 919 | com.na 920 | org.na 921 | nom.nc 922 | com.nf 923 | net.nf 924 | per.nf 925 | rec.nf 926 | web.nf 927 | com.ng 928 | edu.ng 929 | gov.ng 930 | mil.ng 931 | net.ng 932 | org.ng 933 | sch.ng 934 | ac.ni 935 | biz.ni 936 | co.ni 937 | com.ni 938 | edu.ni 939 | gob.ni 940 | in.ni 941 | int.ni 942 | mil.ni 943 | net.ni 944 | nom.ni 945 | org.ni 946 | web.ni 947 | bv.nl 948 | fhs.no 949 | vgs.no 950 | mil.no 951 | dep.no 952 | aa.no 953 | ah.no 954 | bu.no 955 | fm.no 956 | hl.no 957 | hm.no 958 | mr.no 959 | nl.no 960 | nt.no 961 | of.no 962 | ol.no 963 | rl.no 964 | sf.no 965 | st.no 966 | tm.no 967 | tr.no 968 | va.no 969 | vf.no 970 | al.no 971 | ål.no 972 | ås.no 973 | eid.no 974 | fet.no 975 | fla.no 976 | flå.no 977 | gol.no 978 | hof.no 979 | hol.no 980 | ha.no 981 | hå.no 982 | lom.no 983 | sel.no 984 | ski.no 985 | vik.no 986 | biz.nr 987 | gov.nr 988 | edu.nr 989 | org.nr 990 | net.nr 991 | com.nr 992 | ac.nz 993 | co.nz 994 | cri.nz 995 | gen.nz 996 | iwi.nz 997 | mil.nz 998 | net.nz 999 | org.nz 1000 | co.om 1001 | com.om 1002 | edu.om 1003 | gov.om 1004 | med.om 1005 | net.om 1006 | org.om 1007 | pro.om 1008 | ac.pa 1009 | gob.pa 1010 | com.pa 1011 | org.pa 1012 | sld.pa 1013 | edu.pa 1014 | net.pa 1015 | ing.pa 1016 | abo.pa 1017 | med.pa 1018 | nom.pa 1019 | edu.pe 1020 | gob.pe 1021 | nom.pe 1022 | mil.pe 1023 | org.pe 1024 | com.pe 1025 | net.pe 1026 | com.pf 1027 | org.pf 1028 | edu.pf 1029 | com.ph 1030 | net.ph 1031 | org.ph 1032 | gov.ph 1033 | edu.ph 1034 | ngo.ph 1035 | mil.ph 1036 | com.pk 1037 | net.pk 1038 | edu.pk 1039 | org.pk 1040 | fam.pk 1041 | biz.pk 1042 | web.pk 1043 | gov.pk 1044 | gob.pk 1045 | gok.pk 1046 | gon.pk 1047 | gop.pk 1048 | gos.pk 1049 | com.pl 1050 | net.pl 1051 | org.pl 1052 | aid.pl 1053 | atm.pl 1054 | biz.pl 1055 | edu.pl 1056 | gsm.pl 1057 | mil.pl 1058 | nom.pl 1059 | pc.pl 1060 | rel.pl 1061 | sex.pl 1062 | sos.pl 1063 | tm.pl 1064 | gov.pl 1065 | elk.pl 1066 | waw.pl 1067 | gov.pn 1068 | co.pn 1069 | org.pn 1070 | edu.pn 1071 | net.pn 1072 | com.pr 1073 | net.pr 1074 | org.pr 1075 | gov.pr 1076 | edu.pr 1077 | pro.pr 1078 | biz.pr 1079 | est.pr 1080 | ac.pr 1081 | aaa.pro 1082 | aca.pro 1083 | bar.pro 1084 | cpa.pro 1085 | eng.pro 1086 | jur.pro 1087 | law.pro 1088 | med.pro 1089 | edu.ps 1090 | gov.ps 1091 | sec.ps 1092 | plo.ps 1093 | com.ps 1094 | org.ps 1095 | net.ps 1096 | net.pt 1097 | gov.pt 1098 | org.pt 1099 | edu.pt 1100 | int.pt 1101 | com.pt 1102 | co.pw 1103 | ne.pw 1104 | or.pw 1105 | ed.pw 1106 | go.pw 1107 | com.py 1108 | edu.py 1109 | gov.py 1110 | mil.py 1111 | net.py 1112 | org.py 1113 | com.qa 1114 | edu.qa 1115 | gov.qa 1116 | mil.qa 1117 | net.qa 1118 | org.qa 1119 | sch.qa 1120 | com.re 1121 | nom.re 1122 | com.ro 1123 | nom.ro 1124 | nt.ro 1125 | org.ro 1126 | rec.ro 1127 | tm.ro 1128 | www.ro 1129 | ac.rs 1130 | co.rs 1131 | edu.rs 1132 | gov.rs 1133 | in.rs 1134 | org.rs 1135 | ac.ru 1136 | edu.ru 1137 | gov.ru 1138 | int.ru 1139 | mil.ru 1140 | gov.rw 1141 | net.rw 1142 | edu.rw 1143 | ac.rw 1144 | com.rw 1145 | co.rw 1146 | int.rw 1147 | mil.rw 1148 | com.sa 1149 | net.sa 1150 | org.sa 1151 | gov.sa 1152 | med.sa 1153 | pub.sa 1154 | edu.sa 1155 | sch.sa 1156 | com.sb 1157 | edu.sb 1158 | gov.sb 1159 | net.sb 1160 | org.sb 1161 | com.sc 1162 | gov.sc 1163 | net.sc 1164 | org.sc 1165 | edu.sc 1166 | com.sd 1167 | net.sd 1168 | org.sd 1169 | edu.sd 1170 | med.sd 1171 | tv.sd 1172 | gov.sd 1173 | ac.se 1174 | bd.se 1175 | fh.se 1176 | fhv.se 1177 | org.se 1178 | pp.se 1179 | tm.se 1180 | com.sg 1181 | net.sg 1182 | org.sg 1183 | gov.sg 1184 | edu.sg 1185 | per.sg 1186 | com.sh 1187 | net.sh 1188 | gov.sh 1189 | org.sh 1190 | mil.sh 1191 | com.sl 1192 | net.sl 1193 | edu.sl 1194 | gov.sl 1195 | org.sl 1196 | art.sn 1197 | com.sn 1198 | edu.sn 1199 | org.sn 1200 | com.so 1201 | net.so 1202 | org.so 1203 | co.st 1204 | com.st 1205 | edu.st 1206 | gov.st 1207 | mil.st 1208 | net.st 1209 | org.st 1210 | com.sv 1211 | edu.sv 1212 | gob.sv 1213 | org.sv 1214 | red.sv 1215 | gov.sx 1216 | edu.sy 1217 | gov.sy 1218 | net.sy 1219 | mil.sy 1220 | com.sy 1221 | org.sy 1222 | co.sz 1223 | ac.sz 1224 | org.sz 1225 | ac.th 1226 | co.th 1227 | go.th 1228 | in.th 1229 | mi.th 1230 | net.th 1231 | or.th 1232 | ac.tj 1233 | biz.tj 1234 | co.tj 1235 | com.tj 1236 | edu.tj 1237 | go.tj 1238 | gov.tj 1239 | int.tj 1240 | mil.tj 1241 | net.tj 1242 | nic.tj 1243 | org.tj 1244 | web.tj 1245 | gov.tl 1246 | com.tm 1247 | co.tm 1248 | org.tm 1249 | net.tm 1250 | nom.tm 1251 | gov.tm 1252 | mil.tm 1253 | edu.tm 1254 | com.tn 1255 | ens.tn 1256 | fin.tn 1257 | gov.tn 1258 | ind.tn 1259 | nat.tn 1260 | net.tn 1261 | org.tn 1262 | rns.tn 1263 | rnu.tn 1264 | com.to 1265 | gov.to 1266 | net.to 1267 | org.to 1268 | edu.to 1269 | mil.to 1270 | com.tr 1271 | biz.tr 1272 | net.tr 1273 | org.tr 1274 | web.tr 1275 | gen.tr 1276 | tv.tr 1277 | av.tr 1278 | dr.tr 1279 | bbs.tr 1280 | tel.tr 1281 | gov.tr 1282 | bel.tr 1283 | pol.tr 1284 | mil.tr 1285 | edu.tr 1286 | kep.tr 1287 | nc.tr 1288 | co.tt 1289 | com.tt 1290 | org.tt 1291 | net.tt 1292 | biz.tt 1293 | pro.tt 1294 | int.tt 1295 | gov.tt 1296 | edu.tt 1297 | edu.tw 1298 | gov.tw 1299 | mil.tw 1300 | com.tw 1301 | net.tw 1302 | org.tw 1303 | idv.tw 1304 | ac.tz 1305 | co.tz 1306 | go.tz 1307 | me.tz 1308 | mil.tz 1309 | ne.tz 1310 | or.tz 1311 | sc.tz 1312 | tv.tz 1313 | com.ua 1314 | edu.ua 1315 | gov.ua 1316 | in.ua 1317 | net.ua 1318 | org.ua 1319 | ck.ua 1320 | cn.ua 1321 | cr.ua 1322 | cv.ua 1323 | dn.ua 1324 | dp.ua 1325 | if.ua 1326 | kh.ua 1327 | km.ua 1328 | kr.ua 1329 | ks.ua 1330 | kv.ua 1331 | lg.ua 1332 | lt.ua 1333 | lv.ua 1334 | mk.ua 1335 | od.ua 1336 | pl.ua 1337 | rv.ua 1338 | sb.ua 1339 | sm.ua 1340 | te.ua 1341 | uz.ua 1342 | vn.ua 1343 | zp.ua 1344 | zt.ua 1345 | co.ug 1346 | or.ug 1347 | ac.ug 1348 | sc.ug 1349 | go.ug 1350 | ne.ug 1351 | com.ug 1352 | org.ug 1353 | ac.uk 1354 | co.uk 1355 | gov.uk 1356 | ltd.uk 1357 | me.uk 1358 | net.uk 1359 | nhs.uk 1360 | org.uk 1361 | plc.uk 1362 | dni.us 1363 | fed.us 1364 | isa.us 1365 | nsn.us 1366 | ak.us 1367 | al.us 1368 | ar.us 1369 | as.us 1370 | az.us 1371 | ca.us 1372 | co.us 1373 | ct.us 1374 | dc.us 1375 | de.us 1376 | fl.us 1377 | ga.us 1378 | gu.us 1379 | hi.us 1380 | ia.us 1381 | id.us 1382 | il.us 1383 | in.us 1384 | ks.us 1385 | ky.us 1386 | la.us 1387 | ma.us 1388 | md.us 1389 | me.us 1390 | mi.us 1391 | mn.us 1392 | mo.us 1393 | ms.us 1394 | mt.us 1395 | nc.us 1396 | nd.us 1397 | ne.us 1398 | nh.us 1399 | nj.us 1400 | nm.us 1401 | nv.us 1402 | ny.us 1403 | oh.us 1404 | ok.us 1405 | or.us 1406 | pa.us 1407 | pr.us 1408 | ri.us 1409 | sc.us 1410 | sd.us 1411 | tn.us 1412 | tx.us 1413 | ut.us 1414 | vi.us 1415 | vt.us 1416 | va.us 1417 | wa.us 1418 | wi.us 1419 | wv.us 1420 | wy.us 1421 | com.uy 1422 | edu.uy 1423 | gub.uy 1424 | mil.uy 1425 | net.uy 1426 | org.uy 1427 | co.uz 1428 | com.uz 1429 | net.uz 1430 | org.uz 1431 | com.vc 1432 | net.vc 1433 | org.vc 1434 | gov.vc 1435 | mil.vc 1436 | edu.vc 1437 | co.ve 1438 | com.ve 1439 | edu.ve 1440 | gob.ve 1441 | gov.ve 1442 | int.ve 1443 | mil.ve 1444 | net.ve 1445 | org.ve 1446 | rec.ve 1447 | tec.ve 1448 | web.ve 1449 | co.vi 1450 | com.vi 1451 | net.vi 1452 | org.vi 1453 | com.vn 1454 | net.vn 1455 | org.vn 1456 | edu.vn 1457 | gov.vn 1458 | int.vn 1459 | ac.vn 1460 | biz.vn 1461 | pro.vn 1462 | com.vu 1463 | edu.vu 1464 | net.vu 1465 | org.vu 1466 | com.ws 1467 | net.ws 1468 | org.ws 1469 | gov.ws 1470 | edu.ws 1471 | ac.za 1472 | alt.za 1473 | co.za 1474 | edu.za 1475 | gov.za 1476 | law.za 1477 | mil.za 1478 | net.za 1479 | ngo.za 1480 | nis.za 1481 | nom.za 1482 | org.za 1483 | tm.za 1484 | web.za 1485 | ac.zm 1486 | biz.zm 1487 | co.zm 1488 | com.zm 1489 | edu.zm 1490 | gov.zm 1491 | mil.zm 1492 | net.zm 1493 | org.zm 1494 | sch.zm 1495 | ac.zw 1496 | co.zw 1497 | gov.zw 1498 | mil.zw 1499 | org.zw 1500 | cc.ua 1501 | inf.ua 1502 | ltd.ua 1503 | bnr.la 1504 | ae.org 1505 | ar.com 1506 | br.com 1507 | cn.com 1508 | com.de 1509 | com.se 1510 | de.com 1511 | eu.com 1512 | gb.com 1513 | gb.net 1514 | hu.com 1515 | hu.net 1516 | jp.net 1517 | jpn.com 1518 | kr.com 1519 | mex.com 1520 | no.com 1521 | qc.com 1522 | ru.com 1523 | sa.com 1524 | se.net 1525 | uk.com 1526 | uk.net 1527 | us.com 1528 | uy.com 1529 | za.bz 1530 | za.com 1531 | gr.com 1532 | in.net 1533 | us.org 1534 | co.com 1535 | co.ca 1536 | co.cz 1537 | co.nl 1538 | co.no 1539 | biz.dk 1540 | co.dk 1541 | reg.dk 1542 | dy.fi 1543 | ath.cx 1544 | eu.org 1545 | url.tw 1546 | ru.net 1547 | bir.ru 1548 | cbg.ru 1549 | com.ru 1550 | msk.ru 1551 | nov.ru 1552 | spb.ru 1553 | msk.su 1554 | nov.su 1555 | spb.su 1556 | ro.im 1557 | iki.fi 1558 | biz.at 1559 | js.org 1560 | co.krd 1561 | edu.krd 1562 | we.bs 1563 | co.pl 1564 | net.ru 1565 | org.ru 1566 | pp.ru 1567 | nyc.mn 1568 | nom.ae 1569 | nom.af 1570 | nom.ai 1571 | nom.al 1572 | nym.by 1573 | nym.bz 1574 | nom.cl 1575 | nom.gd 1576 | nom.ge 1577 | nom.gl 1578 | nym.gr 1579 | nom.gt 1580 | nym.gy 1581 | nom.hn 1582 | nym.ie 1583 | nom.im 1584 | nom.ke 1585 | nym.kz 1586 | nym.la 1587 | nym.lc 1588 | nom.li 1589 | nym.li 1590 | nym.lt 1591 | nym.lu 1592 | nym.me 1593 | nom.mk 1594 | nym.mn 1595 | nym.mx 1596 | nom.nu 1597 | nym.nz 1598 | nym.pe 1599 | nym.pt 1600 | nom.pw 1601 | nom.qa 1602 | nym.ro 1603 | nom.rs 1604 | nom.si 1605 | nym.sk 1606 | nom.st 1607 | nym.su 1608 | nym.sx 1609 | nom.tj 1610 | nym.tw 1611 | nom.ug 1612 | nom.uy 1613 | nom.vc 1614 | nom.vg 1615 | cya.gg 1616 | nid.io 1617 | own.pm 1618 | ox.rs 1619 | oy.lc 1620 | art.pl 1621 | ras.ru 1622 | hzc.io 1623 | biz.ua 1624 | co.ua 1625 | pp.ua 1626 | gda.pl 1627 | med.pl 1628 | hk.com 1629 | hk.org 1630 | ltd.hk 1631 | inc.hk 1632 | za.net 1633 | za.org 1634 | now.sh 1635 | -------------------------------------------------------------------------------- /icons/dark/neaturl-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-48.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state-1.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state0.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state0_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state0_disabled.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state1.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state2.png -------------------------------------------------------------------------------- /icons/dark/neaturl-96-state3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/dark/neaturl-96-state3.png -------------------------------------------------------------------------------- /icons/light/neaturl-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-48.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state-1.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state0.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state0_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state0_disabled.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state1.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state2.png -------------------------------------------------------------------------------- /icons/light/neaturl-96-state3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/light/neaturl-96-state3.png -------------------------------------------------------------------------------- /icons/neaturl-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-48.png -------------------------------------------------------------------------------- /icons/neaturl-96-state-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state-1.png -------------------------------------------------------------------------------- /icons/neaturl-96-state0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state0.png -------------------------------------------------------------------------------- /icons/neaturl-96-state0_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state0_disabled.png -------------------------------------------------------------------------------- /icons/neaturl-96-state1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state1.png -------------------------------------------------------------------------------- /icons/neaturl-96-state2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state2.png -------------------------------------------------------------------------------- /icons/neaturl-96-state3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/icons/neaturl-96-state3.png -------------------------------------------------------------------------------- /images/Neat URL 4.1.4 in Chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/images/Neat URL 4.1.4 in Chrome.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Neat URL", 3 | "description": "__MSG_extensionDescription__", 4 | "homepage_url": "https://github.com/Smile4ever/Neat-URL", 5 | "manifest_version": 2, 6 | "version": "6.1.0", 7 | "default_locale": "en", 8 | "web_accessible_resources": [ 9 | "data/publicsuffix-ccSLD.txt", 10 | "data/default-params-by-category.json" 11 | ], 12 | "background": { 13 | "scripts": ["browser-polyfill.min.js", "shared.js", "toolbaricon.js", "background.js"] 14 | }, 15 | "content_scripts": [ 16 | { 17 | "matches": [""], 18 | "js": ["shared.js", "neaturl.js"], 19 | "run_at": "document_start" 20 | } 21 | ], 22 | "icons": { 23 | "48": "icons/dark/neaturl-48.png", 24 | "96": "icons/dark/neaturl-96-state0.png" 25 | }, 26 | "applications": { 27 | "gecko": { 28 | "id": "neaturl@hugsmile.eu", 29 | "strict_min_version": "48.0" 30 | } 31 | }, 32 | "permissions": ["storage", "notifications", "contextMenus", "webRequest", "webRequestBlocking", "tabs", ""], 33 | "options_ui": { 34 | "page": "options.html" 35 | }, 36 | "action": { 37 | "default_icon": "icons/dark/neaturl-96-state0.png" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /neaturl.js: -------------------------------------------------------------------------------- 1 | function run(){ 2 | if(enabled_2 == false){ 3 | if(neat_url_logging) console.log("[Neat URL]: disabled on " + window.location.href); 4 | return; 5 | } 6 | 7 | if(neat_url_change_links_in_page){ 8 | var linksOnPage = [...document.querySelectorAll("a")]; 9 | for(var link of linksOnPage){ 10 | if(!link.href.startsWith("http")) continue; 11 | 12 | link.href = cleanURL({url: link.href, type: "DOM"}).redirectUrl; 13 | 14 | if(neat_url_logging) console.log("[Neat URL]: content (DOM) rewrite to " + link.href); 15 | } 16 | }else{ 17 | if(neat_url_logging) console.log("[Neat URL]: content (DOM) disabled on " + window.location.href); 18 | } 19 | } 20 | 21 | window.addEventListener("DOMContentLoaded", async (event) => { 22 | if (event.defaultPrevented) return; 23 | 24 | if(loadedPromise != null) await loadedPromise; 25 | run(); 26 | }); 27 | -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Neat URL 8 | 9 | 10 |
11 | Refresh this page (F5) to see the options of Neat URL 12 |
13 | 14 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | const PREFS = { 2 | "neat_url_override_default_blocked_params": { 3 | "type": "value", 4 | "default": "" 5 | }, 6 | "neat_url_blocked_params": { 7 | "type": "value", 8 | "default": "" 9 | }, 10 | "neat_url_icon_animation": { 11 | "type": "value", 12 | "default": "missing_underscore" 13 | }, 14 | "neat_url_icon_theme": { 15 | "type": "value", 16 | "default": "dark" 17 | }, 18 | "neat_url_show_counter": { 19 | "type": "checked", 20 | "default": true 21 | }, 22 | "neat_url_counter_color": { 23 | "type": "value", 24 | "default": "#eeeeee" 25 | }, 26 | "neat_url_logging": { 27 | "type": "checked", 28 | "default": false 29 | }, 30 | "neat_url_blacklist": { 31 | "type": "value", 32 | "default": "" 33 | }, 34 | "neat_url_types": { 35 | "type": "value", 36 | "default": "main_frame" 37 | }, 38 | "neat_url_counter_default_color": { 39 | "type": "checked", 40 | "default": true 41 | }, 42 | "neat_url_change_links_in_page": { 43 | "type": "checked", 44 | "default": false 45 | } 46 | }; 47 | var lastWidth = 0; 48 | var rendered = false; 49 | 50 | function getClean(text){ 51 | let clean = text.split(","); 52 | 53 | for(let i = 0; i < clean.length; i++){ 54 | clean[i] = clean[i].trim(); 55 | } 56 | 57 | return clean; 58 | } 59 | 60 | async function saveOptions() { 61 | const values = {}; 62 | for(let p in PREFS) { 63 | values[p] = document.querySelector("#"+p)[PREFS[p].type]; 64 | } 65 | 66 | await browser.storage.local.set(values); 67 | browser.runtime.sendMessage({action: "refresh-options"}); 68 | 69 | setTimeout(function(){ 70 | browser.runtime.sendMessage({action: "notify", data: browser.i18n.getMessage("notify_preferences_saved")}); 71 | }, 10); 72 | } 73 | 74 | async function restoreOptions() { 75 | // Default blocked parameters 76 | let response = await fetch('data/default-params-by-category.json').catch(console.error); 77 | let jsonParams = await response.json(); 78 | let categories = jsonParams.categories; 79 | let lines = categories.map(cat => cat.name + ":\n" + cat.params.join(', ')); 80 | document.getElementById("neat_url_default_blocked_params")["value"] = lines.join("\n\n"); 81 | 82 | // Restore preferences 83 | let result = await browser.storage.local.get(Object.keys(PREFS)).catch(console.error); 84 | let val; 85 | for(let p in PREFS) { 86 | if(p in result) { 87 | val = result[p]; 88 | } 89 | else { 90 | val = PREFS[p].default; 91 | } 92 | 93 | console.log("options.js val restored for " + p + " is", val); 94 | document.getElementById(p)[PREFS[p].type] = val; 95 | } 96 | 97 | hideOrShow(); 98 | } 99 | 100 | document.querySelector("#neat_url_counter_default_color").addEventListener("change", function() { 101 | hideOrShow(); 102 | }); 103 | 104 | function hideOrShow(){ 105 | let checked = document.querySelector("#neat_url_counter_default_color").checked; 106 | 107 | if(checked) document.querySelector("#counter_color_element").style.display = "none"; 108 | else document.querySelector("#counter_color_element").style.display = "unset"; 109 | } 110 | 111 | function i18n() { 112 | let i18nElements = document.querySelectorAll('[data-i18n]'); 113 | 114 | for(let i in i18nElements){ 115 | try{ 116 | if(i18nElements[i].getAttribute == null) 117 | continue; 118 | i18n_attrib = i18nElements[i].getAttribute("data-i18n"); 119 | let message = browser.i18n.getMessage(i18n_attrib); 120 | if(message.includes("<") && message.includes(">")){ 121 | i18nElements[i].innerHTML = message; 122 | }else{ 123 | i18nElements[i].textContent = message; 124 | } 125 | }catch(ex){ 126 | console.error("i18n id " + IDS[id] + " not found"); 127 | } 128 | } 129 | } 130 | 131 | async function init(){ 132 | render(); 133 | useCorrectStylesheet(); 134 | restoreOptions(); 135 | i18n(); 136 | document.querySelector("form").style.display = "block"; 137 | document.querySelector(".refreshOptions").style.display = "none"; 138 | } 139 | 140 | function render(){ 141 | if(rendered === false){ 142 | return; // do not render again 143 | } 144 | 145 | rendered = true; 146 | 147 | let sheet = document.styleSheets[0]; 148 | 149 | // https://stackoverflow.com/questions/29927992/remove-css-rules-by-javascript 150 | if (sheet.cssRules) { 151 | for (let i = 0; i < sheet.cssRules.length; i++) { 152 | if (sheet.cssRules[i].selectorText === '.labelbox') { 153 | sheet.deleteRule(i); 154 | } 155 | } 156 | } 157 | 158 | let cssRule = ".labelbox{ min-width: " + newWidth + "px;}"; 159 | sheet.insertRule(cssRule, 1); 160 | lastWidth = newWidth; 161 | } 162 | 163 | function useCorrectStylesheet(){ 164 | let userAgent = navigator.userAgent; 165 | let b = ""; 166 | if(userAgent.includes("Firefox")){ 167 | b = "firefox"; 168 | } 169 | if(userAgent.includes("Chrome")){ 170 | b = "chrome"; 171 | } 172 | 173 | let styles = document.createElement('link'); 174 | styles.rel = "stylesheet"; 175 | styles.type = "text/css"; 176 | styles.media = "screen"; 177 | styles.href = "css/options." + b + ".css"; 178 | document.getElementsByTagName('head')[0].appendChild(styles); 179 | } 180 | 181 | window.addEventListener("DOMContentLoaded", init, { passive: true }); 182 | document.querySelector("form").addEventListener("submit", (e) => { e.preventDefault(); saveOptions(); }, { passive: false }); 183 | window.addEventListener("resize", render); 184 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build:neat-url": "web-ext build --overwrite-dest --ignore-files build.sh images *.md" 4 | }, 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/Smile4ever/Neat-URL.git" 8 | }, 9 | "dependencies": { 10 | "web-ext": "^6.6.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /shared.js: -------------------------------------------------------------------------------- 1 | /// Static variables 2 | let defaultRequestResourceTypes = ["main_frame"]; 3 | let defaultBlacklist = []; // google-analytics.com, sb.scorecardresearch.com, doubleclick.net, beacon.krxd.net" 4 | let suffixList = new Array(); 5 | let loadedPromise = null; 6 | 7 | /// Preferences 8 | let neat_url_logging = false; 9 | let neat_url_show_counter = true; 10 | let neat_url_override_default_blocked_params; 11 | let neat_url_blocked_params_2; 12 | let neat_url_blacklist = []; 13 | let neat_url_change_links_in_page = false; 14 | 15 | let enabled_2 = true; 16 | 17 | // Listen for messages from the content or background script 18 | browser.runtime.onMessage.addListener((message) => { 19 | switch(message.action){ 20 | case "refresh-options": 21 | initOptions(); 22 | break; 23 | default: 24 | break; 25 | } 26 | }); 27 | 28 | function sendMessage(action, data){ 29 | browser.runtime.sendMessage({"action": action, "data": data}).catch((error) => { 30 | console.error("Failed to send " + action + " with data " + data); 31 | }); 32 | } 33 | 34 | function animateToolbarIcon(){ 35 | sendMessage({ 36 | action: "animateToolbarIcon" 37 | }); 38 | } 39 | 40 | function incrementBadgeValue(tabId){ 41 | sendMessage({ 42 | action: "incrementBadgeValue", 43 | data: tabId 44 | }); 45 | } 46 | 47 | let valueOrDefault = function(value, defaultValue){ 48 | if(value == undefined) return defaultValue; 49 | return value; 50 | } 51 | 52 | let valueOrDefaultArray = function(value, defaultValue){ 53 | if(value == undefined || value == "") return defaultValue; 54 | 55 | return value.split("\n").filter(x => !x.includes(":")).join(",").split(" ").join("").split(",").filter(x => x); 56 | } 57 | 58 | async function init(){ 59 | let promise1 = initFiles(); 60 | let promise2 = initOptions(); 61 | 62 | loadedPromise = Promise.all([promise1, promise2]) 63 | await loadedPromise; 64 | loadedPromise = null; 65 | } 66 | 67 | async function initOptions(){ 68 | let storageLocalResult = await browser.storage.local.get([ 69 | "enabled", 70 | "neat_url_logging", 71 | "neat_url_show_counter", 72 | "neat_url_override_default_blocked_params", 73 | "neat_url_blocked_params", 74 | "neat_url_blacklist", 75 | "neat_url_change_links_in_page" 76 | ]).catch(console.error); 77 | 78 | neat_url_logging = valueOrDefault(storageLocalResult.neat_url_logging, false); 79 | neat_url_show_counter = valueOrDefault(storageLocalResult.neat_url_show_counter, true); 80 | 81 | neat_url_override_default_blocked_params = valueOrDefaultArray(storageLocalResult.neat_url_override_default_blocked_params, []); 82 | neat_url_blocked_params_2 = valueOrDefaultArray(storageLocalResult.neat_url_blocked_params, []); 83 | neat_url_blacklist = valueOrDefaultArray(storageLocalResult.neat_url_blacklist, defaultBlacklist); 84 | neat_url_change_links_in_page = valueOrDefault(storageLocalResult.neat_url_change_links_in_page, false); 85 | 86 | enabled_2 = valueOrDefault(storageLocalResult.enabled, true); 87 | } 88 | 89 | async function initFiles(){ 90 | var jsonUrl = browser.runtime.getURL('data/default-params-by-category.json'); 91 | var txtUrl = browser.runtime.getURL('data/publicsuffix-ccSLD.txt'); 92 | 93 | let response = await fetch(jsonUrl); 94 | let jsonParams = await response.json(); 95 | neat_url_default_blocked_params = jsonParams.categories.flatMap(cat => cat.params); 96 | 97 | let response2 = await fetch(txtUrl); 98 | let text = await response2.text(); 99 | suffixList = text.split("\n"); 100 | } 101 | init(); 102 | 103 | String.prototype.replaceAll = function(search, replacement) { 104 | let target = this; 105 | return target.replace(new RegExp(search, 'g'), replacement); 106 | }; 107 | 108 | function removeFromArray(array, item){ 109 | var index = array.indexOf(item); 110 | if (index > -1) { 111 | array.splice(index, 1); 112 | } 113 | 114 | return array; 115 | } 116 | 117 | /// Neat URL code 118 | function removeEndings(leanURL, endingParams){ 119 | let isSearch = leanURL.search == "" ? false : true ; 120 | let path = leanURL.pathname; 121 | 122 | for(let endingParam of endingParams){ 123 | path = applyMatch(endingParam, isSearch, path); 124 | } 125 | 126 | if(leanURL.pathname != path){ 127 | leanURL.pathname = path; 128 | leanURL.search = ""; //should be empty before or removed right now by $$ 129 | } 130 | return leanURL; 131 | } 132 | 133 | function applyMatch(match2, isSearch, leanURL){ 134 | let secondChar = match2.substr(1, 1); 135 | let startIndexAsEnd = -1; 136 | 137 | // /dp/ is for Amazon product pages 138 | if(!isSearch || secondChar == "$" || leanURL.includes("/dp/")){ 139 | // Check it twice 140 | if(match2.indexOf("$") == 0) match2 = match2.substring(1); 141 | if(match2.indexOf("$") == 0) match2 = match2.substring(1); 142 | 143 | startIndexAsEnd = leanURL.lastIndexOf(match2); 144 | //console.log("[Neat URL]: startIndexAsEnd is " + startIndexAsEnd + " inside of " + leanURL + " for " + match2); 145 | 146 | // if startIndexAsEnd is -1, we return the original URL without altering it 147 | if(startIndexAsEnd > -1) 148 | leanURL = leanURL.substring(0, startIndexAsEnd); 149 | } 150 | 151 | return leanURL; 152 | } 153 | 154 | function getParameterForDomainUrl(gbp, domain, rootDomain, domainMinusSuffix, detailsUrl){ 155 | if (!gbp.includes("@")) { 156 | return gbp; 157 | } 158 | 159 | // Workaround for https://github.com/Smile4ever/firefoxaddons/issues/76 160 | if (gbp == "gws_rd@google.*" && rootDomain == "google.com" && detailsUrl.searchParams.get("gws_rd") == "cr"){ 161 | return ""; 162 | } 163 | 164 | let keyValue, keyDomain, index; 165 | index = gbp.indexOf('@'); 166 | [keyValue, keyDomain] = [gbp.slice(0,index), gbp.slice(index+1)]; 167 | 168 | // Root wildcard domain, so compare with root domain 169 | if(keyDomain.startsWith("*.")){ 170 | keyDomain = keyDomain.replace("*.", ""); 171 | if ( rootDomain == keyDomain ) { 172 | //console.log("[Neat URL]: matching to root domain"); 173 | return keyValue; 174 | } 175 | } 176 | 177 | // Suffix wildcard domain 178 | if(keyDomain.endsWith(".*")){ 179 | //console.log("[Neat URL]: keyDomain " + keyDomain + " ends with .* - domainMinusSuffix is " + domainMinusSuffix); 180 | keyDomain = keyDomain.replace(".*", ""); 181 | 182 | if (domainMinusSuffix == keyDomain) { 183 | //console.log("[Neat URL]: matching to wildcard domain"); 184 | return keyValue; 185 | } 186 | } 187 | 188 | // Double wildcards 189 | if(keyDomain.startsWith("*.") && keyDomain.endsWith(".*")){ 190 | keyDomain = keyDomain.replace("*.", ""); 191 | keyDomain = keyDomain.replace(".*", ""); 192 | if ( rootDomain == keyDomain && domainMinusSuffix == keyDomain) { 193 | //console.log("[Neat URL]: matching to root wildcard and suffix wildcard domain"); 194 | return keyValue; 195 | } 196 | } 197 | 198 | if(domain == keyDomain) { 199 | //console.log("[Neat URL]: matching to domain " + domain + " for " + detailsUrl); 200 | return keyValue; 201 | } 202 | 203 | //console.log("[Neat URL]: not matching to domain " + domain + " with keyDomain " + keyDomain); 204 | return ""; 205 | } 206 | 207 | /// Lean URL code 208 | function buildURL(url, blockedParams, hashParams) { 209 | if (blockedParams.length == 0 && hashParams.length == 0) { 210 | return url; 211 | } 212 | 213 | /// Process wildcards parameters 214 | for(let blockedParam of blockedParams){ 215 | // Wildcard support, for example utm_* 216 | let wildcardParam = getWildcardParam(blockedParam); 217 | url = deleteWildcardParam(wildcardParam, url); 218 | } 219 | 220 | /// Replace hash params 221 | let hashUrl = new URL(url.href); 222 | hashUrl.search = hashUrl.hash.replace('#', ''); 223 | hashUrl.hash = ''; 224 | 225 | let searchParamsBefore = hashUrl.href; 226 | 227 | for(let hashParam of hashParams){ 228 | //this will remove one, exact, hashParam 229 | if(hashParam == url.hash || hashParam == "#*" || hashParam == "#?*"){ 230 | url.hash = ""; 231 | return url; 232 | } 233 | 234 | /// Do something special! 235 | // https://github.com/Smile4ever/firefoxaddons/issues/83 236 | // #?utm_source 237 | // Example URL: https://www.cuisineactuelle.fr/recettes/mini-burgers-au-foie-gras-331523#utm_source=Facebook&utm_medium=social&utm_campaign=PassionApero 238 | if (hashParam.startsWith('#?')) { 239 | let specialHashParam = hashParam.replace('#?', ''); 240 | if(neat_url_logging) console.log("[Neat URL]: buildURL - found hash parameter " + hashParam); 241 | 242 | // Wildcard support :) 243 | // utm_* 244 | let wildcardParam = getWildcardParam(specialHashParam); 245 | hashUrl = deleteWildcardParam(wildcardParam, hashUrl); 246 | 247 | // utm_source 248 | hashUrl.searchParams.delete(specialHashParam); 249 | } 250 | } 251 | 252 | // Stringify from URL object adds = to the other parameters without value, sadly. 253 | // In most cases this won't be a problem, if it is there will be bugs about it 254 | // Workaround to above encoding issue: only use the new value if the length is less now 255 | if(searchParamsBefore.length > hashUrl.href.length){ 256 | const newHash = hashUrl.search.replace('?', ''); 257 | url.hash = newHash ? `#${newHash}` : ''; 258 | } 259 | 260 | return url; 261 | } 262 | 263 | function getWildcardParam(param){ 264 | if(param == "*") return param; 265 | 266 | let hasWildcard = param.includes("*"); 267 | if(!hasWildcard) return ""; 268 | 269 | let wildcardIndex = param.indexOf("*"); 270 | let isLastChar = wildcardIndex == param.length - 1; 271 | if(!isLastChar) return ""; 272 | 273 | return param.substring(0, wildcardIndex); 274 | } 275 | 276 | function deleteWildcardParam(wildcardParam, url){ 277 | if(wildcardParam == "") return url; 278 | 279 | // URLSearchParams.keys() and other iterators don't work through X-ray wrappers 280 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1414602 281 | for(let entry of url.searchParams){ 282 | var key = entry[0]; 283 | 284 | if(key.startsWith(wildcardParam) || wildcardParam == "*"){ 285 | // Match! We should remove this parameter. 286 | // Here be dragons ;) 287 | if(neat_url_logging) console.log("[Neat URL]: buildURL - found wildcard parameter " + key + " for " + wildcardParam); 288 | url.searchParams.delete(key); 289 | } 290 | } 291 | 292 | return url; 293 | } 294 | 295 | function getDomainMinusSuffix(domain){ 296 | // Single or double domain 297 | let substringDomainExtension = domain.substring(domain.indexOf(".") + 1); 298 | let substringBeforeDomainExtension = domain.substring(0, domain.indexOf(".")); 299 | 300 | if(suffixList.includes(substringDomainExtension)) 301 | { 302 | return substringBeforeDomainExtension; 303 | } 304 | 305 | // Fallback scenario 306 | let lastIndex = domain.lastIndexOf("."); 307 | let previousLastIndex = domain.lastIndexOf(".", lastIndex - 1); 308 | 309 | if(lastIndex - previousLastIndex < 4){ 310 | lastIndex = previousLastIndex; 311 | } 312 | 313 | return domain.substring(0, lastIndex); 314 | } 315 | 316 | /// Neat URL code 317 | // Copied from https://stackoverflow.com/questions/8498592/extract-hostname-name-from-string 318 | function getRootDomain(domain) { 319 | if(domain == undefined || domain == null) return null; 320 | 321 | let splitArr = domain.split('.'), 322 | arrLen = splitArr.length; 323 | 324 | // grep -e '^[a-zA-Z]\{2,3\}\.[a-zA-Z]\{2,3\}$' publicsuffix.txt > publicsuffix-ccSLD.txt 325 | 326 | // Extract the root domain 327 | //https://publicsuffix.org/list/ 328 | if (arrLen > 2) { 329 | // Checking for double domains with 3 or less characters using publicsuffix-ccSLD.txt. Fixes support *.jd.com for https://item.jd.com 330 | if(splitArr[arrLen - 2].length <= 3){ 331 | var toCheck = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; // co.uk (found) or item.jd.com (not found) 332 | 333 | if(neat_url_logging) console.log("Probably not desired: " + toCheck); 334 | if(neat_url_logging) console.log("Probably more desired: " + splitArr[arrLen - 3] + '.' + splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]); 335 | 336 | if(suffixList.includes(toCheck)){ 337 | // Example URLs that trigger this code path are https://images.google.co.uk and https://google.co.uk 338 | if(neat_url_logging) console.log(toCheck + " found in the list!"); 339 | 340 | domain = splitArr[arrLen - 3] + '.' + splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; 341 | }else{ 342 | if(neat_url_logging) console.log(toCheck + " not found in the list!"); 343 | domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; 344 | } 345 | 346 | }else{ 347 | domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; 348 | } 349 | } 350 | 351 | return domain; 352 | } 353 | 354 | /// Lean URL / Neat URL code 355 | async function cleanURL(details) { 356 | if(!enabled_2) return; 357 | 358 | let url = new URL(details.url); 359 | let domain = url.hostname; 360 | let originalDetailsUrl = details.url; 361 | 362 | // Do not change links for these domains 363 | for(let blackDomain of neat_url_blacklist){ 364 | if(domain.endsWith(blackDomain)){ 365 | if(neat_url_logging) console.log(`[Neat URL]: not rewriting '${url.href}'`); 366 | return; 367 | } 368 | } 369 | 370 | domain = domain.replace(/^www\./i, '');//getDomain() -> //leave www out of this discussion. I don't consider this a subdomain 371 | let rootDomain = getRootDomain(domain); 372 | let domainMinusSuffix = getDomainMinusSuffix(domain); 373 | 374 | if (domain == null || rootDomain == null || domainMinusSuffix == null ){ 375 | return; 376 | } 377 | 378 | let blockedParams = []; 379 | let hashParams = []; 380 | let endingParams = [] 381 | let excludeParams = []; 382 | 383 | let defaultBlockedParamsWithoutOverrides = neat_url_default_blocked_params.filter((defaultBlockedParam) => !neat_url_override_default_blocked_params.includes(defaultBlockedParam)); 384 | let allBlockedParams = defaultBlockedParamsWithoutOverrides.concat(neat_url_blocked_params_2); 385 | 386 | for (let gbp of allBlockedParams) { 387 | let match = getParameterForDomainUrl(gbp, domain, rootDomain, domainMinusSuffix, url); 388 | if(match === "") continue; 389 | 390 | // Hash params 391 | if(match.startsWith("#")){ 392 | if(neat_url_logging) console.log(`[Neat URL]: hash param '${match}' matches (for domain)`); 393 | hashParams.push(match); 394 | continue; 395 | } 396 | 397 | // Ending params 398 | if(match.startsWith("$")){ 399 | if(neat_url_logging) console.log(`[Neat URL]: ending param '${match}' matches (for domain)`); 400 | endingParams.push(match); 401 | continue; 402 | } 403 | 404 | // Excludes 405 | if(match.startsWith("!")){ 406 | if(neat_url_logging) console.log(`[Neat URL]: exclude param '${match}' matches (for domain)`); 407 | excludeParams.push(match); 408 | continue; 409 | } 410 | 411 | blockedParams.push(match); 412 | } 413 | 414 | for(let excludeParam of excludeParams){ 415 | blockedParams = removeFromArray(blockedParams, excludeParam.replace("!", "")); 416 | } 417 | 418 | //! ?a=1&a=2 is valid 419 | // keys must be removed in reverse, 420 | // because, when first is removed, third is moved to second position 421 | let forparams = new URL(url);//or... make copy 422 | 423 | // URLSearchParams.keys() and other iterators don't work through X-ray wrappers 424 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1414602 425 | 426 | for (let entry of forparams.searchParams) { 427 | var key = entry[0]; 428 | if (blockedParams.includes(key)) { 429 | if(neat_url_logging) console.log(`[Neat URL]: delete(${key})`) 430 | url.searchParams.delete(key); 431 | } 432 | } 433 | 434 | var blockedParamsLength = blockedParams 435 | .filter(bp => bp.startsWith("KEY{") && bp.endsWith("}")) 436 | .map(bp => bp.replace("KEY{", "").replace("}", "")); 437 | 438 | for(let blockedParamLength of blockedParamsLength){ 439 | for (let entry of forparams.searchParams) { 440 | var key = entry[0]; 441 | if(blockedParamLength == key.length){ 442 | if(neat_url_logging) console.log(`[Neat URL]: delete(${key}) for rule ${blockedParamLength}`); 443 | url.searchParams.delete(key); 444 | blockedParams = removeFromArray(blockedParams, `KEY{${blockedParamLength}}`); 445 | } 446 | } 447 | } 448 | 449 | // https://github.com/Smile4ever/firefoxaddons/issues/30 should no longer occur with the new buildURL function 450 | // https://github.com/Smile4ever/firefoxaddons/issues/47 should be solved as well 451 | leanURL = buildURL(url, blockedParams, hashParams); 452 | leanURL = removeEndings(leanURL, endingParams); 453 | 454 | // Is the URL changed? 455 | if(new URL(originalDetailsUrl).href == leanURL.href) return; 456 | 457 | if(neat_url_logging) console.log(`[Neat URL]: (type ${details.type}): '${originalDetailsUrl}' has been changed to '${leanURL}'`); 458 | 459 | const applyAfter = 1000; 460 | 461 | if(leanURL.hostname != "addons.mozilla.org"){ 462 | animateToolbarIcon(); 463 | if(neat_url_show_counter) incrementBadgeValue(details.tabId); 464 | } else { 465 | // webRequest blocking is not supported on mozilla.org, lets fix this 466 | // but only if we are navigating to addons.mozilla.org and there doesn't exist a tab yet with the same URL 467 | if(details.type != "main_frame") return; 468 | if(globalNeatURL == leanURL.href) return; 469 | 470 | globalNeatURL = leanURL.href; 471 | globalCurrentURL = originalDetailsUrl; 472 | globalTabId = details.tabId; 473 | 474 | setTimeout(async function(){ 475 | let tabs = await browser.tabs.query({url: globalCurrentURL}); 476 | if(globalNeatURL == null || globalNeatURL == "") return; 477 | 478 | if(tabs.length == 0){ 479 | //console.log(`[Neat URL]: the query for '${globalCurrentURL}' returned nothing. Attempting '${globalNeatURL}'`); 480 | }else{ 481 | //console.log(`[Neat URL]: It was opened in a new tab, update that tab to '${globalNeatURL}'`); 482 | 483 | for (tab of tabs) { 484 | if(neat_url_logging) console.log(`[Neat URL]: really updating '${tab.url}' to '${globalNeatURL}'`); 485 | browser.tabs.update(tab.id, { url: globalNeatURL });//May be fired more than once? 486 | animateToolbarIcon(); 487 | if(neat_url_show_counter) incrementBadgeValue(globalTabId); 488 | } 489 | } 490 | 491 | setTimeout(() => { 492 | globalNeatURL = ""; 493 | globalCurrentURL = ""; 494 | }, applyAfter); 495 | }, applyAfter); 496 | } 497 | 498 | return { redirectUrl: leanURL.href }; 499 | } 500 | -------------------------------------------------------------------------------- /toolbaricon.js: -------------------------------------------------------------------------------- 1 | /// Neat URL code 2 | function updateIcon(){ 3 | if(enabled){ 4 | browser.browserAction.setIcon({path: resolveIconURL("neaturl-96-state0.png")}); 5 | browser.browserAction.setTitle({title: "Neat URL " + version + " - enabled"}); 6 | } 7 | else{ 8 | browser.browserAction.setIcon({path: resolveIconURL("neaturl-96-state0_disabled.png")}); 9 | browser.browserAction.setTitle({title: "Neat URL " + version + " - disabled"}); 10 | } 11 | } 12 | 13 | function animateToolbarIcon(){ 14 | if(neat_url_icon_animation == "none") return; 15 | 16 | let defaultState = resolveIconURL("neaturl-96-state0.png"); 17 | let images = []; 18 | let imagesMissingUnderscore = [resolveIconURL("neaturl-96-state-1.png"), defaultState, resolveIconURL("neaturl-96-state-1.png")]; 19 | let imagesRotate = [resolveIconURL("neaturl-96-state1.png"), resolveIconURL("neaturl-96-state2.png"), resolveIconURL("neaturl-96-state3.png")]; 20 | 21 | if(neat_url_icon_animation == "missing_underscore") 22 | images = imagesMissingUnderscore; 23 | if(neat_url_icon_animation == "rotate") 24 | images = imagesRotate; 25 | 26 | if(images.length == 0 && neat_url_icon_animation == "surprise_me"){ 27 | // https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript 28 | let zeroOrOne = Math.floor(Math.random() * 2); 29 | 30 | if(zeroOrOne == 0) 31 | images = imagesMissingUnderscore; 32 | if(zeroOrOne == 1) 33 | images = imagesRotate; 34 | } 35 | 36 | let time = 350 * images.length; 37 | 38 | // Set first state 39 | browser.browserAction.setIcon({path: images[0]}); 40 | 41 | if(images.length > 1){ 42 | setTimeout(function(){ 43 | browser.browserAction.setIcon({path: images[1]}); 44 | }, 1 * time); 45 | } 46 | 47 | if(images.length > 2){ 48 | setTimeout(function(){ 49 | browser.browserAction.setIcon({path: images[2]}); 50 | }, 2 * time); 51 | } 52 | 53 | // Reset to default state 54 | setTimeout(function(){ 55 | browser.browserAction.setIcon({path: defaultState}); 56 | }, 3 * time); 57 | } 58 | 59 | function resolveIconByTheme(file, theme){ 60 | return "icons/" + theme + "/" + file; 61 | } 62 | 63 | function resolveIconURL(file){ 64 | let theme = neat_url_icon_theme.replace("_notiflight", "").replace("_notifdark", ""); 65 | return resolveIconByTheme(file, theme); 66 | } 67 | 68 | function resolveIconUrlNotif(file){ 69 | if(neat_url_icon_theme.includes("_notiflight")){ 70 | return resolveIconByTheme(file, "light"); 71 | } 72 | if(neat_url_icon_theme.includes("_notifdark")){ 73 | return resolveIconByTheme(file, "dark"); 74 | } 75 | return resolveIconByTheme(file, neat_url_icon_theme); 76 | } 77 | 78 | function updateBadgeText(tabId){ 79 | // We're only updating the view 80 | // The data won't be touched 81 | 82 | //console.log("[Neat URL]: updateBadgeText - I'm updating the badge text for tabId " + tabId); 83 | let badgeCounts = badge[tabId]; 84 | if(badgeCounts == null){ 85 | //console.log("[Neat URL]: badgeCounts == null"); 86 | badgeCounts = ""; // Set empty instead of null or 0 87 | }else{ 88 | //console.log("[Neat URL]: badgeCounts is not null"); 89 | } 90 | 91 | /// Update browserAction with badge count for the current tab. If the current tab changes, we will update it again 92 | //console.log("[Neat URL]: updateBadgeText - badgeCounts is " + badgeCounts); 93 | browser.browserAction.setBadgeText({text: badgeCounts+""}); 94 | } 95 | 96 | function incrementBadgeValue(tabId){ 97 | // We're only updating the data 98 | // The view will be updated when needed by the listeners 99 | 100 | if(tabId == -1) 101 | { 102 | // The request is unrelated to a tab 103 | return; 104 | } 105 | 106 | //console.log("[Neat URL]: getting badgeCounts for tabId " + tabId + " is " + badge[tabId]); 107 | let badgeCounts = badge[tabId]; 108 | if(badgeCounts == null){ 109 | //console.log("[Neat URL]: badgeCounts == null"); 110 | badgeCounts = 0; 111 | }else{ 112 | //console.log("[Neat URL]: badgeCounts is not null, but " + badgeCounts); 113 | } 114 | badgeCounts++; 115 | badge[tabId] = badgeCounts; 116 | 117 | //console.log("[Neat URL]: setting badgeCount to " + badgeCounts + " - result is " + badge[tabId]); 118 | } 119 | 120 | function initCounter(){ 121 | browser.tabs.onCreated.removeListener(onTabCreated); 122 | browser.tabs.onUpdated.removeListener(onTabUpdated); 123 | browser.tabs.onActivated.removeListener(onTabActivated); 124 | browser.tabs.onRemoved.removeListener(onTabRemoved); 125 | 126 | if(neat_url_show_counter){ 127 | browser.tabs.onCreated.addListener(onTabCreated); 128 | browser.tabs.onUpdated.addListener(onTabUpdated); 129 | browser.tabs.onActivated.addListener(onTabActivated); 130 | browser.tabs.onRemoved.addListener(onTabRemoved); 131 | }else{ 132 | // Clear dictionary entirely 133 | badge = []; 134 | } 135 | 136 | // Current tab will be the options page or just an irrelevant tab - no need to update the view with updateBadgeText 137 | } 138 | 139 | function onTabCreated(tab){ 140 | // Tabs can be created in the background. We're not interested in that. 141 | if(!tab.active) return; 142 | 143 | //console.log("[Neat URL]: Updating currentTabId to " + tab.id + " by onCreated"); 144 | updateBadgeText(tab.id); 145 | } 146 | 147 | function onTabUpdated(tabId, changeInfo, tabInfo){ 148 | // Tabs can be updated in the background. We're not interested in that. 149 | if(!tabInfo.active) return; 150 | 151 | //console.log("[Neat URL]: Updating currentTabId to " + tabInfo.id + " by onUpdated"); 152 | updateBadgeText(tabInfo.id); 153 | } 154 | 155 | function onTabActivated(activeInfo){ 156 | // Tabs can be inactive when updating or creating and afterwards activated. We could check tab.active but it will always be true 157 | //console.log("[Neat URL]: Updating currentTabId to " + activeInfo.tabId + " by onActivated"); 158 | updateBadgeText(activeInfo.tabId); 159 | } 160 | 161 | function onTabRemoved(tab){ 162 | // Reset inside "dictionary" 163 | // We're not changing the currentTabId here, since onRemoved will call onActivated implicitly 164 | // We're only resetting the count for the badge, so that if another tab gets the same id, we don't be using the badge count of that unrelated tab 165 | badge[tab.id] = null; 166 | } 167 | 168 | // Keep enabled/disabled state synchronized between tabs 169 | browser.tabs.onActivated.addListener((activeInfo) => { 170 | updateIcon(); 171 | }); 172 | -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-1.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-1.0.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-1.0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-1.0.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-1.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-1.1.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-1.2.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-1.2.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.2.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.3.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.4.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.0.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.0.5.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.1.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.1.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-2.1.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-2.1.2.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-3.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-3.0.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-3.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-3.1.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-3.1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-3.1.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-3.2.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-3.2.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.0.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.0.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.0.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.0.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.1.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.2.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.3.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.4.chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.4.chrome.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.4.firefox.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.4.firefox.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.5.chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.5.chrome.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-4.1.5.firefox.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-4.1.5.firefox.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-5.0.0.chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-5.0.0.chrome.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-5.0.0.firefox.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-5.0.0.firefox.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-6.0.0.chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-6.0.0.chrome.zip -------------------------------------------------------------------------------- /web-ext-artifacts/neat_url-6.0.0.firefox.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Smile4ever/Neat-URL/e75f7f23a7a2a8bc05f0c8363b07783e1cc8e180/web-ext-artifacts/neat_url-6.0.0.firefox.zip --------------------------------------------------------------------------------