1/** 2 * Gulf Currencies Symbol Fix for WooCommerce. 3 * 4 * Adds 'gulf-currency' class to the direct parent element of Gulf currency symbols 5 * to enable proper font rendering. 6 */ 7( function() { 8 'use strict'; 9 10 // Determine class based on context 11 const isAdmin = document.body.classList.contains( 'wp-admin' ); 12 const currencyClass = isAdmin ? 'gulf-currency-dashboard' : 'gulf-currency'; 13 14 // Build symbols array from localized data or fallbacks (SAR=U+20C1, AED=U+E001, OMR=U+E900) 15 const symbols = ( typeof nsrwcGulfCurrencies !== 'undefined' && nsrwcGulfCurrencies.symbols ) 16 ? Object.values( nsrwcGulfCurrencies.symbols ) 17 : [ '\u20C1', '\uE001', '\uE900' ]; 18 19 // Pre-compiled regex for O(1) symbol detection 20 const symbolRegex = new RegExp( '[' + symbols.join( '' ) + ']' ); 21 22 // Track processed elements to avoid duplicate work 23 const processed = new WeakSet(); 24 25 // Debounce state 26 let pending = []; 27 let rafId = null; 28 29 /** 30 * Mark element with currency class. 31 */ 32 function markElement( el ) { 33 if ( el && el.classList && ! processed.has( el ) ) { 34 el.classList.add( currencyClass ); 35 processed.add( el ); 36 } 37 } 38 39 /** 40 * Process a text node - mark its parent if it contains a symbol. 41 */ 42 function processTextNode( node ) { 43 if ( node.nodeValue && symbolRegex.test( node.nodeValue ) ) { 44 markElement( node.parentElement ); 45 } 46 } 47 48 /** 49 * Scan all text nodes in a container. 50 */ 51 function scanContainer( root ) { 52 const walker = document.createTreeWalker( root, NodeFilter.SHOW_TEXT ); 53 let node; 54 while ( ( node = walker.nextNode() ) ) { 55 processTextNode( node ); 56 } 57 } 58 59 /** 60 * Process pending nodes in batched animation frame. 61 */ 62 function flushPending() { 63 rafId = null; 64 const nodes = pending; 65 pending = []; 66 67 for ( let i = 0, len = nodes.length; i < len; i++ ) { 68 const node = nodes[ i ]; 69 if ( node.nodeType === 3 ) { 70 processTextNode( node ); 71 } else if ( node.nodeType === 1 && node.isConnected ) { 72 scanContainer( node ); 73 } 74 } 75 } 76 77 /** 78 * Schedule pending nodes processing. 79 */ 80 function schedulePending() { 81 if ( ! rafId ) { 82 rafId = requestAnimationFrame( flushPending ); 83 } 84 } 85 86 /** 87 * MutationObserver callback. 88 */ 89 function onMutation( mutations ) { 90 for ( let i = 0, len = mutations.length; i < len; i++ ) { 91 const m = mutations[ i ]; 92 93 // Collect added nodes 94 const added = m.addedNodes; 95 for ( let j = 0, jLen = added.length; j < jLen; j++ ) { 96 pending.push( added[ j ] ); 97 } 98 99 // Handle character data changes immediately 100 if ( m.type === 'characterData' ) { 101 processTextNode( m.target ); 102 } 103 } 104 105 if ( pending.length ) { 106 schedulePending(); 107 } 108 } 109 110 // Create observer 111 const observer = new MutationObserver( onMutation ); 112 113 /** 114 * Initialize scanning and observing. 115 */ 116 function init() { 117 scanContainer( document.body ); 118 observer.observe( document.body, { 119 childList: true, 120 subtree: true, 121 characterData: true 122 } ); 123 } 124 125 // Run when ready 126 if ( document.readyState === 'loading' ) { 127 document.addEventListener( 'DOMContentLoaded', init ); 128 } else { 129 init(); 130 } 131} )();
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.