mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 01:02:08 +01:00
Add experimental href-from-text scriptlet
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/2531 Usage: example.com##+js(href-from-text, a[href^="/tracker-link?to="] The above scriptlet will find all elements matching the selector passed as 1st argument, and replace the `href` attribute with the text content of the element, if all the following conditions are met: - The element is a link (`a`) element - The link element has an existing `href` attribute - The text content of the element is a valid `https`-based URL
This commit is contained in:
parent
7bf3f1bd20
commit
e123256eaf
1 changed files with 75 additions and 0 deletions
|
@ -1842,6 +1842,81 @@
|
|||
|
||||
|
||||
|
||||
/// href-from-text.js
|
||||
(function() {
|
||||
let selector = '{{1}}';
|
||||
if ( selector === '{{1}}' ) { selector = ''; }
|
||||
if ( selector === '' ) { return; }
|
||||
const sanitizeCopycats = (href, text) => {
|
||||
let elems = [];
|
||||
try {
|
||||
elems = document.querySelectorAll(`a[href="${href}"`);
|
||||
}
|
||||
catch(ex) {
|
||||
}
|
||||
for ( const elem of elems ) {
|
||||
elem.setAttribute('href', text);
|
||||
}
|
||||
};
|
||||
const sanitize = ( ) => {
|
||||
let elems = [];
|
||||
try {
|
||||
elems = document.querySelectorAll(selector);
|
||||
}
|
||||
catch(ex) {
|
||||
return false;
|
||||
}
|
||||
for ( const elem of elems ) {
|
||||
if ( elem.localName !== 'a' ) { continue; }
|
||||
if ( elem.hasAttribute('href') === false ) { continue; }
|
||||
const href = elem.getAttribute('href');
|
||||
const text = elem.textContent
|
||||
.replace(/^[^\x21-\x7e]+/, '') // remove leading invalid characters
|
||||
.replace(/[^\x21-\x7e]+$/, '') // remove trailing invalid characters
|
||||
;
|
||||
if ( /^https:\/\/./.test(text) === false ) { continue; }
|
||||
if ( /[^\x21-\x7e]/.test(text) ) { continue; }
|
||||
if ( href === text ) { continue; }
|
||||
elem.setAttribute('href', text);
|
||||
sanitizeCopycats(href, text);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
let observer, timer;
|
||||
const onDomChanged = mutations => {
|
||||
if ( timer !== undefined ) { return; }
|
||||
let shouldSanitize = false;
|
||||
for ( const mutation of mutations ) {
|
||||
if ( mutation.addedNodes.length === 0 ) { continue; }
|
||||
for ( const node of mutation.addedNodes ) {
|
||||
if ( node.nodeType !== 1 ) { continue; }
|
||||
shouldSanitize = true;
|
||||
break;
|
||||
}
|
||||
if ( shouldSanitize ) { break; }
|
||||
}
|
||||
if ( shouldSanitize === false ) { return; }
|
||||
timer = self.requestAnimationFrame(( ) => {
|
||||
timer = undefined;
|
||||
sanitize();
|
||||
});
|
||||
};
|
||||
const start = ( ) => {
|
||||
if ( sanitize() === false ) { return; }
|
||||
observer = new MutationObserver(onDomChanged);
|
||||
observer.observe(document.body, {
|
||||
subtree: true,
|
||||
childList: true,
|
||||
});
|
||||
};
|
||||
if ( document.readyState === 'loading' ) {
|
||||
document.addEventListener('DOMContentLoaded', start, { once: true });
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// These lines below are skipped by the resource parser.
|
||||
// <<<< end of private namespace
|
||||
})();
|
||||
|
|
Loading…
Reference in a new issue