-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feature/AG-22709
- Loading branch information
Showing
15 changed files
with
754 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { hit } from './hit'; | ||
import { nodeListToArray } from './array-utils'; | ||
import { getAddedNodes } from './observer'; | ||
import { toRegExp } from './string-utils'; | ||
|
||
/** | ||
* Grabs existing nodes and passes them to a given handler. | ||
* | ||
* @param {string} selector CSS selector to find nodes by | ||
* @param {Function} handler handler to pass nodes to | ||
*/ | ||
export const handleExistingNodes = (selector, handler) => { | ||
const nodeList = document.querySelectorAll(selector); | ||
const nodes = nodeListToArray(nodeList); | ||
handler(nodes); | ||
}; | ||
|
||
/** | ||
* Extracts added nodes from mutations and passes them to a given handler. | ||
* | ||
* @param {MutationRecord[]} mutations mutations to find eligible nodes in | ||
* @param {Function} handler handler to pass eligible nodes to | ||
*/ | ||
export const handleMutations = (mutations, handler) => { | ||
const addedNodes = getAddedNodes(mutations); | ||
handler(addedNodes); | ||
}; | ||
|
||
/** | ||
* Checks if given node's text content should be replaced | ||
* | ||
* @param {Node} node node to check | ||
* @param {RegExp|string} nodeNameMatch regexp or string to match node name | ||
* @param {RegExp|string} textContentMatch regexp or string to match node's text content | ||
* @returns {boolean} true if node's text content should be replaced | ||
*/ | ||
export const isTargetNode = ( | ||
node, | ||
nodeNameMatch, | ||
textContentMatch, | ||
) => { | ||
const { nodeName, textContent } = node; | ||
const nodeNameLowerCase = nodeName.toLowerCase(); | ||
return textContent !== '' | ||
&& (nodeNameMatch instanceof RegExp | ||
? nodeNameMatch.test(nodeNameLowerCase) | ||
: nodeNameMatch === nodeNameLowerCase | ||
) | ||
&& (textContentMatch instanceof RegExp | ||
? textContentMatch.test(textContent) | ||
: textContent.includes(textContentMatch) | ||
); | ||
}; | ||
|
||
/** | ||
* Replaces given node's text content with a given replacement. | ||
* | ||
* @param {string} source source of the scriptlet | ||
* @param {Node} node node to replace text content in | ||
* @param {RegExp|string} pattern pattern to match text content | ||
* @param {string} replacement replacement for matched text content | ||
*/ | ||
export const replaceNodeText = (source, node, pattern, replacement) => { | ||
node.textContent = node.textContent.replace(pattern, replacement); | ||
hit(source); | ||
}; | ||
|
||
/** | ||
* Modifies arguments for trusted-replace-node-text and remove-node-text scriptlets | ||
* | ||
* @param {string} nodeName string or stringified regexp to match node name | ||
* @param {string} textMatch string or stringified regexp to match node's text content | ||
* @param {string} pattern string or stringified regexp to match replace pattern | ||
* @returns {Object} derivative params | ||
*/ | ||
export const parseNodeTextParams = (nodeName, textMatch, pattern = null) => { | ||
const REGEXP_START_MARKER = '/'; | ||
|
||
const isStringNameMatch = !(nodeName.startsWith(REGEXP_START_MARKER) && nodeName.endsWith(REGEXP_START_MARKER)); | ||
const selector = isStringNameMatch ? nodeName : '*'; | ||
const nodeNameMatch = isStringNameMatch | ||
? nodeName | ||
: toRegExp(nodeName); | ||
const textContentMatch = !textMatch.startsWith(REGEXP_START_MARKER) | ||
? textMatch | ||
: toRegExp(textMatch); | ||
|
||
let patternMatch; | ||
if (pattern) { | ||
patternMatch = !pattern.startsWith(REGEXP_START_MARKER) | ||
? pattern | ||
: toRegExp(pattern); | ||
} | ||
|
||
return { | ||
selector, | ||
nodeNameMatch, | ||
textContentMatch, | ||
patternMatch, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { | ||
observeDocumentWithTimeout, | ||
handleExistingNodes, | ||
handleMutations, | ||
replaceNodeText, | ||
isTargetNode, | ||
parseNodeTextParams, | ||
// following helpers should be imported and injected | ||
// because they are used by helpers above | ||
hit, | ||
nodeListToArray, | ||
getAddedNodes, | ||
toRegExp, | ||
} from '../helpers/index'; | ||
|
||
/* eslint-disable max-len */ | ||
/** | ||
* @scriptlet remove-node-text | ||
* | ||
* @description | ||
* Removes text from DOM nodes. | ||
* | ||
* Related UBO scriptlet: | ||
* https://github.com/gorhill/uBlock/commit/2bb446797a12086f2eebc0c8635b671b8b90c477 | ||
* | ||
* ### Syntax | ||
* | ||
* ```adblock | ||
* example.org#%#//scriptlet('remove-node-text', nodeName, condition) | ||
* ``` | ||
* | ||
* - `nodeName` — required, string or RegExp, specifies DOM node name from which the text will be removed. | ||
* Must target lowercased node names, e.g `div` instead of `DIV`. | ||
* - `textMatch` — required, string or RegExp to match against node's text content. | ||
* If matched, the whole text will be removed. Case sensitive. | ||
* | ||
* ### Examples | ||
* | ||
* 1. Remove node's text content: | ||
* | ||
* ```adblock | ||
* example.org#%#//scriptlet('remove-node-text', 'div', 'some text') | ||
* ``` | ||
* | ||
* ```html | ||
* <!-- before --> | ||
* <div>some text</div> | ||
* <span>some text</span> | ||
* | ||
* <!-- after --> | ||
* <div></div > | ||
* <span>some text</span> | ||
* ``` | ||
* | ||
* 2. Remove node's text content, matching both node name and condition by RegExp: | ||
* | ||
* ```adblock | ||
* example.org#%#//scriptlet('remove-node-text', '/[a-z]*[0-9]/', '/text/') | ||
* ``` | ||
* | ||
* ```html | ||
* <!-- before --> | ||
* <qrce3>some text</qrce3> | ||
* <span>some text</span> | ||
* | ||
* <!-- after --> | ||
* <qrce3></qrce3> | ||
* <span>some text</span> | ||
* ``` | ||
* | ||
* @added unreleased. | ||
*/ | ||
/* eslint-enable max-len */ | ||
export function removeNodeText(source, nodeName, textMatch) { | ||
const { | ||
selector, | ||
nodeNameMatch, | ||
textContentMatch, | ||
} = parseNodeTextParams(nodeName, textMatch); | ||
|
||
/** | ||
* Handles nodes by removing text content of matched nodes | ||
* | ||
* Note: instead of drilling down all the arguments for both replace-node-text | ||
* and trusted-replace-node-text scriptlets, only the handler is being passed | ||
* | ||
* @param {Node[]} nodes nodes to handle | ||
* @returns {void} | ||
*/ | ||
const handleNodes = (nodes) => nodes.forEach((node) => { | ||
const shouldReplace = isTargetNode( | ||
node, | ||
nodeNameMatch, | ||
textContentMatch, | ||
); | ||
if (shouldReplace) { | ||
const ALL_TEXT_PATTERN = /^.*$/s; | ||
const REPLACEMENT = ''; | ||
replaceNodeText(source, node, ALL_TEXT_PATTERN, REPLACEMENT); | ||
} | ||
}); | ||
|
||
// Apply dedicated handler to already rendered nodes... | ||
if (document.documentElement) { | ||
handleExistingNodes(selector, handleNodes); | ||
} | ||
|
||
// and newly added nodes | ||
observeDocumentWithTimeout((mutations) => handleMutations(mutations, handleNodes), { | ||
childList: true, | ||
subtree: true, | ||
}); | ||
} | ||
|
||
removeNodeText.names = [ | ||
'remove-node-text', | ||
// aliases are needed for matching the related scriptlet converted into our syntax | ||
'remove-node-text.js', | ||
'rmnt.js', | ||
]; | ||
|
||
removeNodeText.injections = [ | ||
observeDocumentWithTimeout, | ||
handleExistingNodes, | ||
handleMutations, | ||
replaceNodeText, | ||
isTargetNode, | ||
parseNodeTextParams, | ||
// following helpers should be imported and injected | ||
// because they are used by helpers above | ||
hit, | ||
nodeListToArray, | ||
getAddedNodes, | ||
toRegExp, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.