1/** 2 * Queries an element and throws if not found. 3 * Defaults to HTMLElement to allow access to properties like .hidden, .style, etc. 4 * 5 * @template {HTMLElement} T 6 * @param {ParentNode} scope 7 * @param {string} selector 8 * @returns {T} 9 */ 10export function ensureOneEl(scope, selector) { 11 const all = scope.querySelectorAll(selector); 12 if (all.length === 0) { 13 throw new Error(`Element not found: ${selector}`); 14 } 15 if (all.length > 1) { 16 console.error(`Multiple elements match selector: "${selector}"`); 17 } 18 return /** @type {T} */ (all[0]); 19} 20 21/** 22 * Registers event listeners once per key on document by aborting any previous subscription. 23 * 24 * @param {string} key 25 * @param {(signal: AbortSignal) => void} register 26 * @returns {void} 27 */ 28export function subscribeDocumentOnce(key, register) { 29 const controller = new AbortController(); 30 const cleanup = () => controller.abort(); 31 32 const doc = 33 /** @type {Document & Record<string, undefined | (() => void)>} */ ( 34 document 35 ); 36 const previous = doc[key]; 37 if (typeof previous === "function") { 38 previous(); 39 } 40 doc[key] = cleanup; 41 42 register(controller.signal); 43} 44 45/** 46 * @param {string} name 47 * @returns {string | null} 48 */ 49export function readCookie(name) { 50 const match = document.cookie.match(new RegExp(`(^|; )${name}=([^;]+)`)); 51 if (!match) { 52 return null; 53 } 54 try { 55 return decodeURIComponent(match[2]); 56 } catch { 57 return match[2]; 58 } 59} 60 61/** @param {string} name */ 62export function clearCookie(name) { 63 document.cookie = `${name}=; Max-Age=0; Path=/`; 64} 65 66/** 67 * @param {string} varName 68 * @returns {Promise<any>} 69 */ 70export function waitWindowAttr(varName) { 71 return new Promise((resolve) => { 72 function ready() {
73 if (varName in window) { 74 resolve(/** @type {any} */ (window)[varName]); 75 return; 76 } 77 setTimeout(ready, 100); 78 } 79 ready(); 80 }); 81}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.