Skip to content

Commit 2bb4467

Browse files
committed
Add remove-node-text.js scriptlet
The scriptlet remove the *whole* text of a DOM node. Usage: example.com##+js(remote-node-text, nodeName, condition, ...) Where `condition` is a pattern to find in the target node for the removal to occur. Since the text of the node is wholly removed, this is not a scriplet which requires a trusted-source, as it is virtually a similar capability as removing DOM nodes through procedural cosmetic operator `:remove()` (which can't target `#text` nodes), which does not require trusted-source. Alias: `rmnt` The extra parameters are the same as those documented for `replace-node-text`. For consistency, the alias for `replace-node-text` has been renamed `rpnt`.
1 parent 1ff31e0 commit 2bb4467

File tree

1 file changed

+113
-74
lines changed

1 file changed

+113
-74
lines changed

assets/resources/scriptlets.js

Lines changed: 113 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,93 @@ function setConstantCore(
527527
}, options);
528528
}
529529

530+
/******************************************************************************/
531+
532+
builtinScriptlets.push({
533+
name: 'replace-node-text-core.fn',
534+
fn: replaceNodeTextCore,
535+
dependencies: [
536+
'get-extra-args.fn',
537+
'pattern-to-regex.fn',
538+
'run-at.fn',
539+
'safe-self.fn',
540+
],
541+
});
542+
function replaceNodeTextCore(
543+
nodeName = '',
544+
pattern = '',
545+
replacement = ''
546+
) {
547+
const reNodeName = patternToRegex(nodeName, 'i');
548+
const rePattern = patternToRegex(pattern, 'gms');
549+
const extraArgs = getExtraArgs(Array.from(arguments), 3);
550+
const shouldLog = scriptletGlobals.has('canDebug') && extraArgs.log || 0;
551+
const reCondition = patternToRegex(extraArgs.condition || '', 'gms');
552+
const safe = safeSelf();
553+
const stop = (takeRecord = true) => {
554+
if ( takeRecord ) {
555+
handleMutations(observer.takeRecords());
556+
}
557+
observer.disconnect();
558+
if ( shouldLog !== 0 ) {
559+
safe.uboLog(`sed.js: quitting "${pattern}" => "${replacement}"`);
560+
}
561+
};
562+
let sedCount = extraArgs.sedCount || 0;
563+
const handleNode = node => {
564+
const before = node.textContent;
565+
if ( safe.RegExp_test.call(rePattern, before) === false ) { return true; }
566+
if ( safe.RegExp_test.call(reCondition, before) === false ) { return true; }
567+
const after = pattern !== ''
568+
? before.replace(rePattern, replacement)
569+
: replacement;
570+
node.textContent = after;
571+
if ( shouldLog !== 0 ) {
572+
safe.uboLog('sed.js before:\n', before);
573+
safe.uboLog('sed.js after:\n', after);
574+
}
575+
return sedCount === 0 || (sedCount -= 1) !== 0;
576+
};
577+
const handleMutations = mutations => {
578+
for ( const mutation of mutations ) {
579+
for ( const node of mutation.addedNodes ) {
580+
if ( reNodeName.test(node.nodeName) === false ) { continue; }
581+
if ( handleNode(node) ) { continue; }
582+
stop(false); return;
583+
}
584+
}
585+
};
586+
const observer = new MutationObserver(handleMutations);
587+
observer.observe(document, { childList: true, subtree: true });
588+
if ( document.documentElement ) {
589+
const treeWalker = document.createTreeWalker(
590+
document.documentElement,
591+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT
592+
);
593+
let count = 0;
594+
for (;;) {
595+
const node = treeWalker.nextNode();
596+
count += 1;
597+
if ( node === null ) { break; }
598+
if ( reNodeName.test(node.nodeName) === false ) { continue; }
599+
if ( handleNode(node) ) { continue; }
600+
stop(); break;
601+
}
602+
if ( shouldLog !== 0 ) {
603+
safe.uboLog(`sed.js ${count} nodes present before installing mutation observer`);
604+
}
605+
}
606+
if ( extraArgs.stay ) { return; }
607+
runAt(( ) => {
608+
const quitAfter = extraArgs.quitAfter || 0;
609+
if ( quitAfter !== 0 ) {
610+
setTimeout(( ) => { stop(); }, quitAfter);
611+
} else {
612+
stop();
613+
}
614+
}, 'interactive');
615+
}
616+
530617
/*******************************************************************************
531618
532619
Injectable scriptlets
@@ -2304,6 +2391,25 @@ function spoofCSS(
23042391
});
23052392
}
23062393

2394+
/******************************************************************************/
2395+
2396+
builtinScriptlets.push({
2397+
name: 'remove-node-text.js',
2398+
aliases: [ 'rmnt.js' ],
2399+
fn: removeNodeText,
2400+
world: 'ISOLATED',
2401+
dependencies: [
2402+
'replace-node-text-core.fn',
2403+
],
2404+
});
2405+
function removeNodeText(
2406+
nodeName,
2407+
condition,
2408+
...extraArgs
2409+
) {
2410+
replaceNodeTextCore(nodeName, '', '', 'condition', condition || '', ...extraArgs);
2411+
}
2412+
23072413
/*******************************************************************************
23082414
*
23092415
* Scriplets below this section are only available for filter lists from
@@ -2343,87 +2449,20 @@ function spoofCSS(
23432449
builtinScriptlets.push({
23442450
name: 'replace-node-text.js',
23452451
requiresTrust: true,
2346-
aliases: [ 'rnt.js', 'sed.js' /* to be removed */ ],
2452+
aliases: [ 'rpnt.js', 'sed.js' /* to be removed */ ],
23472453
fn: replaceNodeText,
23482454
world: 'ISOLATED',
23492455
dependencies: [
2350-
'get-extra-args.fn',
2351-
'pattern-to-regex.fn',
2352-
'run-at.fn',
2353-
'safe-self.fn',
2456+
'replace-node-text-core.fn',
23542457
],
23552458
});
23562459
function replaceNodeText(
2357-
nodeName = '',
2358-
pattern = '',
2359-
replacement = ''
2460+
nodeName,
2461+
pattern,
2462+
replacement,
2463+
...extraArgs
23602464
) {
2361-
const reNodeName = patternToRegex(nodeName, 'i');
2362-
const rePattern = patternToRegex(pattern, 'gms');
2363-
const extraArgs = getExtraArgs(Array.from(arguments), 3);
2364-
const shouldLog = scriptletGlobals.has('canDebug') && extraArgs.log || 0;
2365-
const reCondition = patternToRegex(extraArgs.condition || '', 'gms');
2366-
const safe = safeSelf();
2367-
const stop = (takeRecord = true) => {
2368-
if ( takeRecord ) {
2369-
handleMutations(observer.takeRecords());
2370-
}
2371-
observer.disconnect();
2372-
if ( shouldLog !== 0 ) {
2373-
safe.uboLog(`sed.js: quitting "${pattern}" => "${replacement}"`);
2374-
}
2375-
};
2376-
let sedCount = extraArgs.sedCount || 0;
2377-
const handleNode = node => {
2378-
const before = node.textContent;
2379-
if ( safe.RegExp_test.call(rePattern, before) === false ) { return true; }
2380-
if ( safe.RegExp_test.call(reCondition, before) === false ) { return true; }
2381-
const after = before.replace(rePattern, replacement);
2382-
node.textContent = after;
2383-
if ( shouldLog !== 0 ) {
2384-
safe.uboLog('sed.js before:\n', before);
2385-
safe.uboLog('sed.js after:\n', after);
2386-
}
2387-
return sedCount === 0 || (sedCount -= 1) !== 0;
2388-
};
2389-
const handleMutations = mutations => {
2390-
for ( const mutation of mutations ) {
2391-
for ( const node of mutation.addedNodes ) {
2392-
if ( reNodeName.test(node.nodeName) === false ) { continue; }
2393-
if ( handleNode(node) ) { continue; }
2394-
stop(false); return;
2395-
}
2396-
}
2397-
};
2398-
const observer = new MutationObserver(handleMutations);
2399-
observer.observe(document, { childList: true, subtree: true });
2400-
if ( document.documentElement ) {
2401-
const treeWalker = document.createTreeWalker(
2402-
document.documentElement,
2403-
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT
2404-
);
2405-
let count = 0;
2406-
for (;;) {
2407-
const node = treeWalker.nextNode();
2408-
count += 1;
2409-
if ( node === null ) { break; }
2410-
if ( reNodeName.test(node.nodeName) === false ) { continue; }
2411-
if ( handleNode(node) ) { continue; }
2412-
stop(); break;
2413-
}
2414-
if ( shouldLog !== 0 ) {
2415-
safe.uboLog(`sed.js ${count} nodes present before installing mutation observer`);
2416-
}
2417-
}
2418-
if ( extraArgs.stay ) { return; }
2419-
runAt(( ) => {
2420-
const quitAfter = extraArgs.quitAfter || 0;
2421-
if ( quitAfter !== 0 ) {
2422-
setTimeout(( ) => { stop(); }, quitAfter);
2423-
} else {
2424-
stop();
2425-
}
2426-
}, 'interactive');
2465+
replaceNodeTextCore(nodeName, pattern, replacement, ...extraArgs);
24272466
}
24282467

24292468
/*******************************************************************************

0 commit comments

Comments
 (0)