├── LICENSE ├── README.md └── scriptlets.js /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2023 uBlock-user 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # uBO-Scriptlets 2 | A custom arsenal of scriptlets to be used for injecting userscripts via uBlock Origin. 3 | 4 | CDN - https://ubo-scriptlets.pages.dev/scriptlets.js 5 | 6 | CDN2 - https://ublocko.github.io/uBO-Scriptlets/scriptlets.js 7 | 8 | # Installation 9 | 10 | Add [uBO-Scriptlets](https://ubo-scriptlets.pages.dev/scriptlets.js) to `userResourcesLocation` parameter in `Advanced-Settings` in uBlock-Origin. 11 | -------------------------------------------------------------------------------- /scriptlets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /// remove-node.js 4 | /// world ISOLATED 5 | /// alias rmn.js 6 | /// dependency run-at.fn 7 | /// dependency safe-self.fn 8 | function removeNode( 9 | element = '', 10 | needle = '' 11 | ) { 12 | if ( element === '') { return; } 13 | const safe = safeSelf(); 14 | const reNeedle = safe.patternToRegex(needle); 15 | const removenode = () => { 16 | try { 17 | const nodes = document.querySelectorAll(element); 18 | if ( nodes.length > 0 ) { 19 | for (const node of nodes) { 20 | if (reNeedle.test(node.outerHTML)) { 21 | node.remove(); 22 | } 23 | } 24 | } 25 | } catch { } 26 | }; 27 | let observer, timer; 28 | const onDomChanged = mutations => { 29 | if ( timer !== undefined ) { return; } 30 | let shouldWork = false; 31 | for ( const mutation of mutations ) { 32 | if ( mutation.addedNodes.length === 0 ) { continue; } 33 | for ( const node of mutation.addedNodes ) { 34 | if ( node.nodeType !== 1 ) { continue; } 35 | shouldWork = true; 36 | break; 37 | } 38 | if ( shouldWork ) { break; } 39 | } 40 | if ( shouldWork === false ) { return; } 41 | timer = self.requestAnimationFrame(( ) => { 42 | timer = undefined; 43 | removenode(); 44 | }); 45 | }; 46 | const start = ( ) => { 47 | if ( removenode() === false ) { return; } 48 | observer = new MutationObserver(onDomChanged); 49 | observer.observe(document.body, { 50 | subtree: true, 51 | childList: true, 52 | }); 53 | }; 54 | runAt(( ) => { start(); }, 'interactive'); 55 | } 56 | 57 | /// rename-attr.js 58 | /// alias rna.js 59 | /// world ISOLATED 60 | /// dependency run-at.fn 61 | // example.com##+js(rna, [selector], oldattr, newattr) 62 | function renameAttr( 63 | selector = '', 64 | oldattr = '', 65 | newattr = '' 66 | ) { 67 | if ( selector === '' || oldattr === '' || newattr === '' ) { return; } 68 | const renameattr = ( ) => { 69 | const elems = document.querySelectorAll(selector); 70 | try { 71 | for ( const elem of elems ) { 72 | if ( elem.hasAttribute( oldattr ) ) { 73 | const value = elem.getAttribute( oldattr ); 74 | elem.removeAttribute( oldattr ); 75 | elem.setAttribute( newattr, value ); 76 | } 77 | } 78 | } catch { } 79 | }; 80 | let observer, timer; 81 | const onDomChanged = mutations => { 82 | if ( timer !== undefined ) { return; } 83 | let shouldWork = false; 84 | for ( const mutation of mutations ) { 85 | if ( mutation.addedNodes.length === 0 ) { continue; } 86 | for ( const node of mutation.addedNodes ) { 87 | if ( node.nodeType !== 1 ) { continue; } 88 | shouldWork = true; 89 | break; 90 | } 91 | if ( shouldWork ) { break; } 92 | } 93 | if ( shouldWork === false ) { return; } 94 | timer = self.requestAnimationFrame(( ) => { 95 | timer = undefined; 96 | renameattr(); 97 | }); 98 | }; 99 | const start = ( ) => { 100 | if ( renameattr() === false ) { return; } 101 | observer = new MutationObserver(onDomChanged); 102 | observer.observe(document.body, { 103 | subtree: true, 104 | childList: true, 105 | }); 106 | }; 107 | runAt(( ) => { start(); }, 'interactive'); 108 | } 109 | 110 | /// replace-attr.js 111 | /// alias rpla.js 112 | /// world ISOLATED 113 | /// dependency run-at.fn 114 | // example.com##+js(rpla, [selector], oldattr, newattr, newvalue) 115 | function replaceAttr( 116 | selector = '', 117 | oldattr = '', 118 | newattr = '', 119 | value = '' 120 | ) { 121 | if ( selector === '' || oldattr === '' || newattr === '' ) { return; } 122 | const replaceattr = ( ) => { 123 | const elems = document.querySelectorAll(selector); 124 | try { 125 | for ( const elem of elems ) { 126 | if ( elem.hasAttribute( oldattr ) ) { 127 | elem.removeAttribute( oldattr ); 128 | elem.setAttribute( newattr, value ); 129 | } 130 | } 131 | } catch { } 132 | }; 133 | let observer, timer; 134 | const onDomChanged = mutations => { 135 | if ( timer !== undefined ) { return; } 136 | let shouldWork = false; 137 | for ( const mutation of mutations ) { 138 | if ( mutation.addedNodes.length === 0 ) { continue; } 139 | for ( const node of mutation.addedNodes ) { 140 | if ( node.nodeType !== 1 ) { continue; } 141 | shouldWork = true; 142 | break; 143 | } 144 | if ( shouldWork ) { break; } 145 | } 146 | if ( shouldWork === false ) { return; } 147 | timer = self.requestAnimationFrame(( ) => { 148 | timer = undefined; 149 | replaceattr(); 150 | }); 151 | }; 152 | const start = ( ) => { 153 | if ( replaceattr() === false ) { return; } 154 | observer = new MutationObserver(onDomChanged); 155 | observer.observe(document.body, { 156 | subtree: true, 157 | childList: true, 158 | }); 159 | }; 160 | runAt(( ) => { start(); }, 'interactive'); 161 | } 162 | 163 | /// add-class.js 164 | /// alias ac.js 165 | /// dependency run-at.fn 166 | /// world ISOLATED 167 | // example.com##+js(ac, class, [selector]) 168 | function addClass( 169 | needle = '', 170 | selector = '' 171 | ) { 172 | if ( needle === '' ) { return; } 173 | const needles = needle.split(/\s*\|\s*/); 174 | if ( selector === '' ) { selector = '.' + needles.map(a => CSS.escape(a)).join(',.'); } 175 | const addclass = ( ) => { 176 | const nodes = document.querySelectorAll(selector); 177 | try { 178 | for ( const node of nodes ) { 179 | if ( !node.classList.contains(...needles) ) { 180 | node.classList.add(...needles); 181 | } 182 | } 183 | } catch { } 184 | }; 185 | let observer, timer; 186 | const onDomChanged = mutations => { 187 | if ( timer !== undefined ) { return; } 188 | let shouldWork = false; 189 | for ( const mutation of mutations ) { 190 | if ( mutation.addedNodes.length === 0 ) { continue; } 191 | for ( const node of mutation.addedNodes ) { 192 | if ( node.nodeType !== 1 ) { continue; } 193 | shouldWork = true; 194 | break; 195 | } 196 | if ( shouldWork ) { break; } 197 | } 198 | if ( shouldWork === false ) { return; } 199 | timer = self.requestAnimationFrame(( ) => { 200 | timer = undefined; 201 | addclass(); 202 | }); 203 | }; 204 | const start = ( ) => { 205 | if ( addclass() === false ) { return; } 206 | observer = new MutationObserver(onDomChanged); 207 | observer.observe(document.body, { 208 | subtree: true, 209 | childList: true, 210 | }); 211 | }; 212 | runAt(( ) => { start(); }, 'interactive'); 213 | } 214 | 215 | /// replace-class.js 216 | /// alias rpc.js 217 | /// world ISOLATED 218 | /// dependency run-at.fn 219 | // example.com##+js(rpc, [selector], oldclass, newclass) 220 | function replaceClass( 221 | selector = '', 222 | oldclass = '', 223 | newclass = '' 224 | ) { 225 | if ( selector === '' || oldclass === '' || newclass === '' ) { return; } 226 | const replaceclass = ( ) => { 227 | const nodes = document.querySelectorAll(selector); 228 | try { 229 | for ( const node of nodes ) { 230 | if ( node.classList.contains(oldclass) ) { 231 | node.classList.replace(oldclass, newclass); 232 | } 233 | } 234 | } catch { } 235 | }; 236 | let observer, timer; 237 | const onDomChanged = mutations => { 238 | if ( timer !== undefined ) { return; } 239 | let shouldWork = false; 240 | for ( const mutation of mutations ) { 241 | if ( mutation.addedNodes.length === 0 ) { continue; } 242 | for ( const node of mutation.addedNodes ) { 243 | if ( node.nodeType !== 1 ) { continue; } 244 | shouldWork = true; 245 | break; 246 | } 247 | if ( shouldWork ) { break; } 248 | } 249 | if ( shouldWork === false ) { return; } 250 | timer = self.requestAnimationFrame(( ) => { 251 | timer = undefined; 252 | replaceclass(); 253 | }); 254 | }; 255 | const start = ( ) => { 256 | if ( replaceclass() === false ) { return; } 257 | observer = new MutationObserver(onDomChanged); 258 | observer.observe(document.body, { 259 | subtree: true, 260 | childList: true, 261 | }); 262 | }; 263 | runAt(( ) => { start(); }, 'interactive'); 264 | } 265 | 266 | /// append-elem.js 267 | /// alias ape.js 268 | /// dependency run-at.fn 269 | /// world ISOLATED 270 | // example.com##+js(ape, [selector], element, attribute, value) 271 | function appendElem( 272 | selector = '', 273 | elem = '', 274 | attr = '', 275 | value = '' 276 | ) { 277 | if ( selector === '' ) { return; } 278 | const appendNode = ( ) => { 279 | try { 280 | const elements = document.querySelectorAll(selector); 281 | for ( const element of elements ) { 282 | const node = document.createElement(elem); 283 | node.setAttribute(attr, value); 284 | element.append(node); 285 | } 286 | } catch { } 287 | }; 288 | runAt(( ) => { appendNode(); }, 'interactive'); 289 | } 290 | 291 | /// callfunction.js 292 | /// alias cf.js 293 | /// dependency run-at.fn 294 | // example.com##+js(cf, funcName) 295 | function callFunction( 296 | funcCall = '' 297 | ) { 298 | if ( funcCall === '' ) { return; } 299 | const funcInvoke = ( ) => { 300 | try { 301 | self.requestAnimationFrame(funcCall) 302 | } catch { } 303 | }; 304 | runAt(( ) => { funcInvoke(); }, 'idle'); 305 | } 306 | 307 | /// insert-child-before.js 308 | /// alias icb.js 309 | /// world ISOLATED 310 | /// dependency run-at.fn 311 | // example.com##+js(icb, element, node) 312 | function insertChildBefore( 313 | selector = '', 314 | element = '', 315 | run = '' 316 | ) { 317 | if ( selector === '' || element === '' ) { return; } 318 | let timer; 319 | const insertelem = () => { 320 | timer = undefined; 321 | try { 322 | const elems = document.querySelectorAll(selector); 323 | const nodes = document.querySelectorAll(element); 324 | for (let i = 0; i < elems.length; i++) { 325 | elems[i].before(nodes[i]); 326 | } 327 | } catch { } 328 | }; 329 | const mutationHandler = mutations => { 330 | if ( timer !== undefined ) { return; } 331 | let skip = true; 332 | for ( let i = 0; i < mutations.length && skip; i++ ) { 333 | const { type, addedNodes, removedNodes } = mutations[i]; 334 | if ( type === 'attributes' ) { skip = false; } 335 | for ( let j = 0; j < addedNodes.length && skip; j++ ) { 336 | if ( addedNodes[j].nodeType === 1 ) { skip = false; break; } 337 | } 338 | for ( let j = 0; j < removedNodes.length && skip; j++ ) { 339 | if ( removedNodes[j].nodeType === 1 ) { skip = false; break; } 340 | } 341 | } 342 | if ( skip ) { return; } 343 | timer = self.requestAnimationFrame(insertelem); 344 | }; 345 | const start = ( ) => { 346 | insertelem(); 347 | if ( /\bloop\b/.test(run) === false ) { return; } 348 | const observer = new MutationObserver(mutationHandler); 349 | observer.observe(document.documentElement, { 350 | childList: true, 351 | subtree: true, 352 | }); 353 | }; 354 | runAt(( ) => { start(); }, /\bcomplete\b/.test(run) ? 'idle' : 'interactive'); 355 | } 356 | 357 | /// insert-child-after.js 358 | /// alias ica.js 359 | /// world ISOLATED 360 | /// dependency run-at.fn 361 | // example.com##+js(ica, element, node) 362 | function insertChildAfter( 363 | selector = '', 364 | element = '', 365 | run = '' 366 | ) { 367 | if ( selector === '' || element === '' ) { return; } 368 | let timer; 369 | const insertelem = () => { 370 | timer = undefined; 371 | try { 372 | const elems = document.querySelectorAll(selector); 373 | const nodes = document.querySelectorAll(element); 374 | for (let i = 0; i < elems.length; i++) { 375 | elems[i].after(nodes[i]); 376 | } 377 | } catch { } 378 | }; 379 | const mutationHandler = mutations => { 380 | if ( timer !== undefined ) { return; } 381 | let skip = true; 382 | for ( let i = 0; i < mutations.length && skip; i++ ) { 383 | const { type, addedNodes, removedNodes } = mutations[i]; 384 | if ( type === 'attributes' ) { skip = false; } 385 | for ( let j = 0; j < addedNodes.length && skip; j++ ) { 386 | if ( addedNodes[j].nodeType === 1 ) { skip = false; break; } 387 | } 388 | for ( let j = 0; j < removedNodes.length && skip; j++ ) { 389 | if ( removedNodes[j].nodeType === 1 ) { skip = false; break; } 390 | } 391 | } 392 | if ( skip ) { return; } 393 | timer = self.requestAnimationFrame(insertelem); 394 | }; 395 | const start = ( ) => { 396 | insertelem(); 397 | if ( /\bloop\b/.test(run) === false ) { return; } 398 | const observer = new MutationObserver(mutationHandler); 399 | observer.observe(document.documentElement, { 400 | childList: true, 401 | subtree: true, 402 | }); 403 | }; 404 | runAt(( ) => { start(); }, /\bcomplete\b/.test(run) ? 'idle' : 'interactive'); 405 | } 406 | 407 | /// set-inner-html.js 408 | /// alias sih.js 409 | /// dependency run-at.fn 410 | /// world ISOLATED 411 | function setInnerHTML( 412 | selector = '', 413 | text = '' 414 | ) { 415 | if ( selector === '' || text === '' ) { return; } 416 | const innerHTML = ( ) => { 417 | const nodes = document.querySelectorAll(selector); 418 | try { 419 | for ( const node of nodes ) { 420 | if ( node ) { node.innerHTML = text; } 421 | } 422 | } catch { } 423 | }; 424 | runAt(( ) => { innerHTML(); }, 'interactive'); 425 | } 426 | 427 | /// move-attr-prop.js 428 | /// alias map.js 429 | /// dependency run-at.fn 430 | /// world ISOLATED 431 | // example.com##+js(map, [selector], [selector2], attr, attr2) 432 | function moveAttrProp( 433 | selector = '', 434 | element = '', 435 | newattr = '', 436 | oldattr = '' 437 | ) { 438 | if ( selector === '' || element === '') { return; } 439 | const map = ( ) => { 440 | try { 441 | const elem = document.querySelectorAll(selector); 442 | const elem2 = document.querySelectorAll(element); 443 | for (let i = 0; i < elem.length; i++) { 444 | elem[i].setAttribute(newattr, elem2[i].getAttribute(oldattr)); 445 | } 446 | } catch { } 447 | }; 448 | runAt(( ) => { map(); }, 'interactive'); 449 | } 450 | --------------------------------------------------------------------------------