// ==UserScript== // @name Aliexpress Url Cleaner // @version 0.3 // @description Removes unnecessary parameters to Aliexpress urls // @match *://*.aliexpress.com/* // @namespace https://greasyfork.org/users/168 // @run-at document-start // @grant unsafeWindow // @noframes // @downloadURL none // ==/UserScript== function whenReady() { return new Promise((resolve) => { function completed() { document.removeEventListener('DOMContentLoaded', completed); window.removeEventListener('load', completed); resolve(); } if (document.readyState === 'complete' || document.readyState === 'interactive') { resolve(); } else { document.addEventListener('DOMContentLoaded', completed); window.addEventListener('load', completed); } }); } // Required by firefox to make functions available to page scripts. function exportFn(fn, target, name) { if (typeof exportFunction === 'function') { exportFunction(fn, target, { defineAs: name }); } else { target[name] = fn; } } let reg = /((?:https?:)?\/\/(?:\w+\.)?aliexpress\.com\/(?:store\/product\/[^\/]+\/[0-9_]+|item\/(?:[^\/]+\/)?[0-9_]+)\.html)(\?[^#\r\n]+)?(#.+)?/i; function toCanonical(original) { let match = original.match(reg); if (match) { return match[1] + (match[3] || ''); } return null; } // For lazy-loaded links. Mutation observer listening to jsonP requests. let observer = new MutationObserver(function (mutationsList) { for (let mutation of mutationsList) { for (let node of mutation.addedNodes) { const match = (node.src || '').match(/(\/getI2iRecommendingResults\.do|\/b2bad\.html).+[?|&](?:callback|cb)=(__jp\d+)/); if (match) { let requestUrl = match[1]; let callbackName = match[2]; let originalCallback = unsafeWindow[callbackName]; function objCleaner(obj) { try { if (requestUrl === '/getI2iRecommendingResults.do' && obj.success) { for (let product of obj.results) { let canonical = toCanonical(product.productDetailUrl) if (canonical) { product.productDetailUrl = canonical; } } } else if (requestUrl === '/b2bad.html') { for (let product of obj.PRODUCTS) { let canonical = toCanonical(product.DETAILURL) if (canonical) { product.DETAILURL = canonical; } } } } catch (e) { } originalCallback(obj); } exportFn(objCleaner, unsafeWindow, callbackName); }; } } }); observer.observe(document.head, { childList: true }); // Tab url. let canonical = toCanonical(window.location.href); if (!canonical) { let link = document.querySelector('head > link[rel=canonical]'); if (link) { canonical = toCanonical(link.href + window.location.hash); } } if (canonical) { window.history.replaceState(history.state, document.title, canonical); } // Non lazy-loaded links. whenReady().then(() => { document.querySelectorAll('a').forEach((e) => { let canonical = toCanonical(e.href); if (canonical) { e.href = canonical; } }); });