SyntaxError: Unexpected token '<', "(({ SRC_ELEMEMENTS_QUERY = [], listenAfterMs = 2_500, } = {}) => { const EVENTS_PREVENT_DEFAULT_MANDATORY = [ 'submit' ] const EVENTS = [ 'mouseover', 'click', 'submit', 'input', 'blur', 'change', 'focus', 'invalid', ] const addListener = ({ srcElement, eventName, listeners, afterExecuteListeners }) => { srcElement?.addEventListener(eventName, (e) => { executeListeners({ e, srcElement, listeners, afterExecuteListeners }) }) } const executeListeners = async ({ e, srcElement, listeners, afterExecuteListeners }) => { await Promise.all( (listeners ?? []).map((listener) => { if (listener) return listener({ e, srcElement }) }) ) if (afterExecuteListeners) await afterExecuteListeners() } const getListenerFromScript = ({ script, eventName }) => { if (!script) return null if (script[eventName]) return script[eventName] const prev = Object.keys(script)?.find((key) => script[key][eventName]) if (!prev) return null return script[prev][eventName] } const fetchListeners = async ({ srcElement, eventName, e }) => { if (!srcElement?.getAttribute) return const scriptNames = srcElement?.getAttribute(`on-${eventName}`) if (!scriptNames) return if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault() const scripts = await Promise.all( scriptNames?.split(',')?.map((scriptName) => { const scriptToImport = `/${scriptName?.trim()}.js` return importScriptDynamically({ path: scriptToImport }) }) ) const listeners = scripts?.map((script) => getListenerFromScript({ script, eventName })) return listeners } const addScripts = () => { const scriptsToLoad = [...document.querySelectorAll('script[data-script-to-load]')] return Promise.all( scriptsToLoad?.map((scriptToLoad) => { const id = scriptToLoad?.getAttribute('data-script-to-load') scriptToLoad.removeAttribute('data-script-to-load') const attrs = scriptToLoad?.getAttributeNames()?.reduce((acc, attrName) => { const attrValue = scriptToLoad.getAttribute(attrName) if (attrValue !== 'text/script-to-load') acc[attrName] = attrValue return acc }, {}) const content = scriptToLoad?.textContent scriptToLoad?.remove() return loadScript({ id, attrs, content }).catch((err) => { console.error(err) }) }) ) } const loadScript = ({ id, attrs, content }) => { const script = document?.createElement('script') Object.keys(attrs)?.forEach((attrKey) => script?.setAttribute(attrKey, attrs[attrKey])) script.id = id script.type = 'module' if (content) script?.insertAdjacentHTML('beforeend', content) return new Promise((resolve, reject) => { if (!attrs.src) { resolve() document?.body?.insertAdjacentElement('beforeend', script) return } script.onload = script.onreadystatechange = function () { if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') { resolve() script.onload = script.onreadystatechange = null } } script.onerror = () => { console.error('script failed to load') reject(new Error(`Failed to load script with src ${script.src}`)) } document?.body?.insertAdjacentElement('beforeend', script) }) } // FIX: return import() to prevent __vitePreload to take action const importScriptDynamically = ({ path }) => { return import(path)?.catch((err) => { }) } // load const fireLoadListener = () => { const eventName = 'load' const srcElements = document?.querySelectorAll(`[on-${eventName}]`) srcElements?.forEach(async (srcElement) => { const listeners = await fetchListeners({ srcElement, eventName, e: null }) executeListeners({ e: null, srcElement, listeners }) srcElement?.removeAttribute(`on-${eventName}`) }) } // invalid const fireInvalidListener = () => { const eventName = 'invalid' const srcElements = document?.querySelectorAll(`[on-${eventName}]`) srcElements?.forEach(async (srcElement) => { const listeners = await fetchListeners({ srcElement, eventName, e: null }) addListener({ srcElement, eventName, listeners }) }) } // blur const fireBlurListener = () => { const eventName = 'blur' const srcElements = document?.querySelectorAll(`[on-${eventName}]`) srcElements?.forEach(async (srcElement) => { const listeners = await fetchListeners({ srcElement, eventName, e: null }) addListener({ srcElement, eventName, listeners }) }) } // focus const fireFocusListener = () => { const eventName = 'focus' const srcElements = document?.querySelectorAll(`[on-${eventName}]`) srcElements?.forEach(async (srcElement) => { const listeners = await fetchListeners({ srcElement, eventName, e: null }) addListener({ srcElement, eventName, listeners }) }) } // observers const fireObserverListeners = () => { const srcElements = [...document.querySelectorAll('[on-observe]')] const uniqueScriptNames = [...srcElements?.reduce((acc, srcElement) => { const attribute = srcElement?.getAttribute('on-observe') if (attribute === 'undefined') return acc const scriptNames = attribute?.split(',') scriptNames?.forEach((scriptName) => acc?.set(scriptName, 1)) return acc }, new Map())?.keys()] uniqueScriptNames?.forEach(async (scriptName) => { const observedSrcElements = document.querySelectorAll(`[on-observe*="${scriptName}"]`) const script = await importScriptDynamically({ path: `/${scriptName?.trim()}.js` }) const listener = getListenerFromScript({ script, eventName: 'observe' }) if (!listener) return const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => listener({ entry, observer })) }, { threshold: .5, }) observedSrcElements?.forEach((observerSrcElement) => { observer.observe(observerSrcElement) const observerAttr = observerSrcElement?.getAttribute('on-observe') const updatedObserverAttr = observerAttr?.replaceAll(scriptName + ', ', '')?.replaceAll(', ' + scriptName, '')?.replaceAll(scriptName, '') if (!updatedObserverAttr) observerSrcElement.removeAttribute('on-observe') else observerSrcElement.setAttribute('on-observe', updatedObserverAttr) }) }) } const getSrcElement = ({ srcElement, eventName }) => { if (!srcElement?.hasAttribute) return srcElement const attribute = `on-${eventName}` const hasScriptName = srcElement?.hasAttribute(attribute) if (hasScriptName) return srcElement const query = `:is(${['a', 'button', ...SRC_ELEMEMENTS_QUERY].join(',')})[${attribute}]` const closestButton = srcElement?.closest(query) if (closestButton) return closestButton return srcElement } const cloneSrcElement = ({ srcElement }) => { const newSrcElement = document.createElement(srcElement?.tagName) Array.from(srcElement?.attributes).forEach((attr) => { if (attr.name.startsWith('on-')) return newSrcElement.setAttribute(attr.name, attr.value) }) return newSrcElement } const isAnchorBeingClicked = ({ srcElement, eventName }) => { return srcElement?.tagName === 'A' && eventName === 'click' } const clickDefaultAnchor = ({ srcElement }) => { const newAnchor = cloneSrcElement({ srcElement }) newAnchor.click() } const fireListeners = () => { EVENTS.forEach((eventName) => { document.body[`on${eventName}`] = async (e) => { const srcElement = getSrcElement({ srcElement: e?.srcElement, eventName }) const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName }) if (isAnchorClicked) e.preventDefault() const listeners = await fetchListeners({ srcElement, eventName, e }) const afterExecuteListeners = isAnchorClicked ? () => { clickDefaultAnchor({ srcElement }) } : null executeListeners({ e, srcElement, listeners, afterExecuteListeners }) addListener({ srcElement, eventName, listeners, afterExecuteListeners }) if (srcElement?.removeAttribute) srcElement.removeAttribute(`on-${eventName}`) } }) const saloeListenEvent = new CustomEvent('saloeListen', { detail: { message: 'This is a custom eventName!' } }) document.body.addEventListener('saloeListen', async (e) => { await addScripts() fireLoadListener() fireObserverListeners() }) document.body.saloeListen = function () { document.body.dispatchEvent(saloeListenEvent) } } fireListeners() window.onload = () => { setTimeout(() => { document.body.saloeListen() }, listenAfterMs) } })({ SRC_ELEMEMENTS_QUERY: ["u"], listenAfterMs: 500 })