Skip to content

Commit

Permalink
Add JSDoc comment
Browse files Browse the repository at this point in the history
Check if cssPropertyName and cssPropertyValue are set
Use debug instead of shouldDebug
Use template strings
Add convertSpoofCssArgs method to converter
Add conversion tests
  • Loading branch information
AdamWr committed Jan 19, 2024
1 parent c7ef889 commit a12558a
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 16 deletions.
27 changes: 26 additions & 1 deletion src/helpers/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ const UBO_NO_FETCH_IF_WILDCARD = '/^/';
const ESCAPED_COMMA_SEPARATOR = '\\,';
const COMMA_SEPARATOR = ',';

const SPOOF_CSS_METHOD = 'spoofCSS';
const REMOVE_ATTR_METHOD = 'removeAttr';
const REMOVE_CLASS_METHOD = 'removeClass';
const SPOOF_CSS_ALIASES = scriptletList[SPOOF_CSS_METHOD].names;
const REMOVE_ATTR_ALIASES = scriptletList[REMOVE_ATTR_METHOD].names;
const REMOVE_CLASS_ALIASES = scriptletList[REMOVE_CLASS_METHOD].names;
const REMOVE_ATTR_CLASS_APPLYING = ['asap', 'stay', 'complete'];
Expand Down Expand Up @@ -157,7 +159,7 @@ const validateRemoveAttrClassArgs = (parsedArgs: string[]): string[] => {
// https://github.com/AdguardTeam/Scriptlets/issues/133
const lastArg = restArgs.pop() as string; // https://github.com/microsoft/TypeScript/issues/30406
let applying;
// check the last parsed arg for matching possible 'applying' vale
// check the last parsed arg for matching possible 'applying' value
if (REMOVE_ATTR_CLASS_APPLYING.some((el) => lastArg.includes(el))) {
applying = lastArg;
} else {
Expand All @@ -180,6 +182,25 @@ const validateRemoveAttrClassArgs = (parsedArgs: string[]): string[] => {
return validArgs;
};

/**
* Convert uBO spoof-css scriptlet selectors argument to AdGuard syntax
*
* @param parsedArgs scriptlet arguments
* @returns converted args
*/
const convertSpoofCssArgs = (parsedArgs: string[]): string[] => {
const [name, selectors, ...restArgs] = parsedArgs;
// in uBO selectors are separated by escaped commas
// so it's necessary to replace it with just commas
const selector = replaceAll(
selectors,
ESCAPED_COMMA_SEPARATOR,
COMMA_SEPARATOR,
);
const convertedArgs = [name, selector, ...restArgs];
return convertedArgs;
};

/**
* Converts string of UBO scriptlet rule to AdGuard scriptlet rule
*
Expand All @@ -206,6 +227,10 @@ export const convertUboScriptletToAdg = (rule: string): string[] => {
parsedArgs = validateRemoveAttrClassArgs(parsedArgs);
}

if (SPOOF_CSS_ALIASES.includes(scriptletName)) {
parsedArgs = convertSpoofCssArgs(parsedArgs);
}

const args = parsedArgs
.map((arg, index) => {
let outputArg = arg;
Expand Down
27 changes: 16 additions & 11 deletions src/scriptlets/spoof-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import {
* ### Syntax
*
* ```text
* example.org#%#//scriptlet('spoof-css'[, selectors[, cssNameProperty[, cssNameValue[, shouldDebug]]]])
* example.org#%#//scriptlet('spoof-css', selectors, cssNameProperty, cssNameValue[, shouldDebug])
* ```
*
* - `selectors` — string of comma-separated selectors to match
* - `cssPropertyName` — CSS property name, separated by a comma
* - `cssPropertyValue` — CSS property value, separated by a comma
* - `shouldDebug` — optional, defaults to `false`, if set to `true`, will trigger debugger statement
* - `debug` — optional, if set to `debug`, will trigger debugger statement
* when `getComputedStyle()` or `getBoundingClientRect()` methods is called
*
*
Expand Down Expand Up @@ -56,7 +56,7 @@ import {
*/
/* eslint-enable max-len */

export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, shouldDebug = false) {
export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, debug) {
if (!selectors) {
return;
}
Expand All @@ -67,17 +67,22 @@ export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, s
'ubo-spoof-css',
];

// getComputedStyle uses camelCase version of CSS properties
// for example, "clip-path" is displayed as "clipPath"
// so it's needed to convert CSS property to camelCase
/**
* getComputedStyle uses camelCase version of CSS properties
* for example, "clip-path" is displayed as "clipPath"
* so it's needed to convert CSS property to camelCase
*
* @param {string} cssProperty
* @returns {string} camelCase version of CSS property
*/
function convertToCamelCase(cssProperty) {
if (!cssProperty.includes('-')) {
return cssProperty;
}
const splittedProperty = cssProperty.split('-');
const firstPart = splittedProperty[0];
const secondtPart = splittedProperty[1];
return firstPart + secondtPart[0].toUpperCase() + secondtPart.slice(1);
const secondPart = splittedProperty[1];
return `${firstPart}${secondPart[0].toUpperCase()}${secondPart.slice(1)}`;
}

const propToValueMap = new Map();
Expand Down Expand Up @@ -109,7 +114,7 @@ export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, s
}
propToValueMap.set(convertToCamelCase(arrayOfProperties[i]), arrayOfProperties[i + 1]);
}
} else {
} else if (cssPropertyName && cssPropertyValue) {
const arrayOfCssNames = cssPropertyName.replace(/\s+/g, '').split(',');
const arrayOfCssValues = cssPropertyValue.replace(/\s+/g, '').split(',');

Expand Down Expand Up @@ -146,7 +151,7 @@ export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, s
};

const getComputedStyleWrapper = (target, thisArg, args) => {
if (shouldDebug) {
if (debug === 'debug') {
debugger; // eslint-disable-line no-debugger
}
const style = Reflect.apply(target, thisArg, args);
Expand Down Expand Up @@ -201,7 +206,7 @@ export function spoofCSS(source, selectors, cssPropertyName, cssPropertyValue, s
window.getComputedStyle = new Proxy(window.getComputedStyle, getComputedStyleHandler);

const getBoundingClientRectWrapper = (target, thisArg, args) => {
if (shouldDebug) {
if (debug === 'debug') {
debugger; // eslint-disable-line no-debugger
}
const rect = Reflect.apply(target, thisArg, args);
Expand Down
18 changes: 18 additions & 0 deletions tests/api/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ describe('Test scriptlet api methods', () => {
actual: 'example.com##+js(set-session-storage-item, acceptCookies, false)',
expected: "example.com#%#//scriptlet('ubo-set-session-storage-item.js', 'acceptCookies', 'false')",
},
{
actual: 'example.com##+js(spoof-css, .advert, display, block)',
expected: "example.com#%#//scriptlet('ubo-spoof-css.js', '.advert', 'display', 'block')",
},
{
actual: 'example.com##+js(spoof-css, .adsbygoogle\\, #ads\\, .adTest, visibility, visible)',
// eslint-disable-next-line max-len
expected: "example.com#%#//scriptlet('ubo-spoof-css.js', '.adsbygoogle, #ads, .adTest', 'visibility', 'visible')",
},
];
test.each(validTestCases)('$actual', ({ actual, expected }) => {
expect(convertScriptletToAdg(actual)[0]).toStrictEqual(expected);
Expand Down Expand Up @@ -308,6 +317,15 @@ describe('Test scriptlet api methods', () => {
actual: String.raw`example.com#%#//scriptlet('adjust-setInterval', ',dataType:_', '1000', '0.02')`,
expected: String.raw`example.com##+js(nano-setInterval-booster, \,dataType:_, 1000, 0.02)`,
},
{
actual: "example.com#%#//scriptlet('spoof-css', '.advert', 'display', 'block')",
expected: 'example.com##+js(spoof-css, .advert, display, block)',
},
{
// eslint-disable-next-line max-len
actual: "example.com#%#//scriptlet('spoof-css', '.adsbygoogle, #ads, .adTest', 'visibility', 'visible')",
expected: 'example.com##+js(spoof-css, .adsbygoogle\\, #ads\\, .adTest, visibility, visible)',
},
];
test.each(testCases)('$actual', ({ actual, expected }) => {
expect(convertAdgScriptletToUbo(actual)).toStrictEqual(expected);
Expand Down
28 changes: 24 additions & 4 deletions tests/scriptlets/spoof-css.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test('Checking if alias name works', (assert) => {

// uBO has a different arguments sequence, so we need to test it separately
test('Check uBO alias', (assert) => {
const matchClassName = 'testClass';
const matchClassName = 'testClassUboAlias';

const matchElem = createElem(matchClassName);
const cssProperty = 'display: none !important;';
Expand Down Expand Up @@ -127,7 +127,7 @@ test('Check uBO alias - two elements', (assert) => {
});

test('Check uBO alias with debug', (assert) => {
const matchClassName = 'testClass';
const matchClassName = 'testClassUboDebug';

const matchElem = createElem(matchClassName);
const cssProperty = 'display: none !important;';
Expand Down Expand Up @@ -163,7 +163,7 @@ test('Check uBO alias with debug', (assert) => {
});

test('One selector and one property - getComputedStyle', (assert) => {
const matchClassName = 'testClass';
const matchClassName = 'testClassGetComputedStyle';

const matchElem = createElem(matchClassName);
const cssProperty = 'display: none !important;';
Expand All @@ -185,6 +185,26 @@ test('One selector and one property - getComputedStyle', (assert) => {
matchStyle.remove();
});

test('Only selector - do nothing', (assert) => {
const matchClassName = 'testClassNothing';

const matchElem = createElem(matchClassName);
const cssProperty = 'display: none !important;';
const matchStyle = addStyle(`.${matchClassName} { ${cssProperty} }`);

const scriptletArgs = [`.${matchClassName}`];
runScriptlet(name, scriptletArgs);

const elStyle = window.getComputedStyle(matchElem).display;

assert.strictEqual(elStyle, 'none', 'display style is set to none');
assert.strictEqual(window.hit, 'FIRED');

clearGlobalProps('hit');
matchElem.remove();
matchStyle.remove();
});

test('One selector and one property + test element which style should not be changed - getComputedStyle', (assert) => {
const matchClassNameChange = 'testClassChange';
const matchClassNameNotChange = 'testClassNotChange';
Expand Down Expand Up @@ -214,7 +234,7 @@ test('One selector and one property + test element which style should not be cha
});

test('One selector and non existed property - getComputedStyle', (assert) => {
const matchClassName = 'testClass';
const matchClassName = 'testClassNotExistedProperty';

const matchElem = createElem(matchClassName);
const cssProperty = 'display: none !important;';
Expand Down

0 comments on commit a12558a

Please sign in to comment.