Skip to content

Commit e613282

Browse files
committed
Improve set-cookie scriptlet
Allow negative integer as valid value. Related issue: #3927 Additionally, move cookie-related scriptlets/helpers into its own source code file.
1 parent 652f178 commit e613282

File tree

3 files changed

+545
-441
lines changed

3 files changed

+545
-441
lines changed

assets/resources/set-attr.js renamed to assets/resources/attribute.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,108 @@ trustedSetAttr.details = {
198198
world: 'ISOLATED',
199199
};
200200

201+
/**
202+
* @scriptlet remove-attr
203+
*
204+
* @description
205+
* Remove one or more attributes from a set of elements.
206+
*
207+
* @param attribute
208+
* The name of the attribute(s) to remove. This can be a list of space-
209+
* separated attribute names.
210+
*
211+
* @param [selector]
212+
* Optional. A CSS selector for the elements to target. Default to
213+
* `[attribute]`, or `[attribute1],[attribute2],...` if more than one
214+
* attribute name is specified.
215+
*
216+
* @param [behavior]
217+
* Optional. Space-separated tokens which modify the default behavior.
218+
* - `asap`: Try to remove the attribute as soon as possible. Default behavior
219+
* is to remove the attribute(s) asynchronously.
220+
* - `stay`: Keep trying to remove the specified attribute(s) on DOM mutations.
221+
* */
222+
223+
export function removeAttr(
224+
rawToken = '',
225+
rawSelector = '',
226+
behavior = ''
227+
) {
228+
if ( typeof rawToken !== 'string' ) { return; }
229+
if ( rawToken === '' ) { return; }
230+
const safe = safeSelf();
231+
const logPrefix = safe.makeLogPrefix('remove-attr', rawToken, rawSelector, behavior);
232+
const tokens = rawToken.split(/\s*\|\s*/);
233+
const selector = tokens
234+
.map(a => `${rawSelector}[${CSS.escape(a)}]`)
235+
.join(',');
236+
if ( safe.logLevel > 1 ) {
237+
safe.uboLog(logPrefix, `Target selector:\n\t${selector}`);
238+
}
239+
const asap = /\basap\b/.test(behavior);
240+
let timerId;
241+
const rmattrAsync = ( ) => {
242+
if ( timerId !== undefined ) { return; }
243+
timerId = safe.onIdle(( ) => {
244+
timerId = undefined;
245+
rmattr();
246+
}, { timeout: 17 });
247+
};
248+
const rmattr = ( ) => {
249+
if ( timerId !== undefined ) {
250+
safe.offIdle(timerId);
251+
timerId = undefined;
252+
}
253+
try {
254+
const nodes = document.querySelectorAll(selector);
255+
for ( const node of nodes ) {
256+
for ( const attr of tokens ) {
257+
if ( node.hasAttribute(attr) === false ) { continue; }
258+
node.removeAttribute(attr);
259+
safe.uboLog(logPrefix, `Removed attribute '${attr}'`);
260+
}
261+
}
262+
} catch(ex) {
263+
}
264+
};
265+
const mutationHandler = mutations => {
266+
if ( timerId !== undefined ) { return; }
267+
let skip = true;
268+
for ( let i = 0; i < mutations.length && skip; i++ ) {
269+
const { type, addedNodes, removedNodes } = mutations[i];
270+
if ( type === 'attributes' ) { skip = false; }
271+
for ( let j = 0; j < addedNodes.length && skip; j++ ) {
272+
if ( addedNodes[j].nodeType === 1 ) { skip = false; break; }
273+
}
274+
for ( let j = 0; j < removedNodes.length && skip; j++ ) {
275+
if ( removedNodes[j].nodeType === 1 ) { skip = false; break; }
276+
}
277+
}
278+
if ( skip ) { return; }
279+
asap ? rmattr() : rmattrAsync();
280+
};
281+
const start = ( ) => {
282+
rmattr();
283+
if ( /\bstay\b/.test(behavior) === false ) { return; }
284+
const observer = new MutationObserver(mutationHandler);
285+
observer.observe(document, {
286+
attributes: true,
287+
attributeFilter: tokens,
288+
childList: true,
289+
subtree: true,
290+
});
291+
};
292+
runAt(( ) => { start(); }, behavior.split(/\s+/));
293+
}
294+
removeAttr.details = {
295+
name: 'remove-attr.js',
296+
aliases: [
297+
'ra.js',
298+
],
299+
dependencies: [
300+
runAt,
301+
safeSelf,
302+
],
303+
};
304+
201305
/******************************************************************************/

0 commit comments

Comments
 (0)