{"version":3,"file":"index.cjs","sources":["../src/util.ts","../src/index.ts","../src/queue.ts","../src/observer.ts"],"sourcesContent":["/**\n * Check if the user's connection is configured and fast enough\n * to preload data in the background.\n */\nexport function networkSupportsPreloading(): boolean {\n\tif (navigator.connection) {\n\t\tif (navigator.connection.saveData) {\n\t\t\treturn false;\n\t\t}\n\t\tif (navigator.connection.effectiveType?.endsWith('2g')) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Does this device support true hover/pointer interactions?\n */\nexport function deviceSupportsHover() {\n\treturn window.matchMedia('(hover: hover)').matches;\n}\n\n/**\n * Is this element an anchor element?\n */\nexport function isAnchorElement(element: unknown): element is HTMLAnchorElement | SVGAElement {\n\treturn !!element && (element instanceof HTMLAnchorElement || element instanceof SVGAElement);\n}\n\n/**\n * Safe requestIdleCallback function that falls back to setTimeout\n */\nexport const whenIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));\n","import Plugin from '@swup/plugin';\nimport { getCurrentUrl, Location } from 'swup';\nimport type {\n\tDelegateEvent,\n\tDelegateEventHandler,\n\tDelegateEventUnsubscribe,\n\tPageData,\n\tHookDefaultHandler\n} from 'swup';\nimport {\n\tdeviceSupportsHover,\n\tnetworkSupportsPreloading,\n\twhenIdle,\n\tisAnchorElement\n} from './util.js';\nimport createQueue, { Queue } from './queue.js';\nimport createObserver, { Observer } from './observer.js';\n\ndeclare module 'swup' {\n\texport interface Swup {\n\t\t/**\n\t\t * Preload links by passing in either:\n\t\t * - a URL or an array of URLs\n\t\t * - a link element or an array of link elements\n\t\t */\n\t\tpreload?: SwupPreloadPlugin['preload'];\n\t\t/**\n\t\t * Preload any links on the current page manually marked for preloading.\n\t\t */\n\t\tpreloadLinks?: () => void;\n\t}\n\texport interface HookDefinitions {\n\t\t'link:hover': { el: HTMLAnchorElement | SVGAElement; event: DelegateEvent };\n\t\t'page:preload': { url: string; page?: PageData };\n\t}\n\texport interface HookReturnValues {\n\t\t'page:preload': Promise<PageData>;\n\t}\n}\n\nexport type AnchorElement = HTMLAnchorElement | SVGAElement;\n\ntype VisibleLinkPreloadOptions = {\n\t/** Enable preloading of links entering the viewport */\n\tenabled: boolean;\n\t/** How much area of a link must be visible to preload it: 0 to 1.0 */\n\tthreshold: number;\n\t/** How long a link must be visible to preload it, in milliseconds */\n\tdelay: number;\n\t/** Containers to look for links in */\n\tcontainers: string[];\n\t/** Callback for opting out selected elements from preloading */\n\tignore: (el: AnchorElement) => boolean;\n};\n\nexport type PluginOptions = {\n\t/** The *concurrency limit* for simultaneous requests when preloading. */\n\tthrottle: number;\n\t/** Preload the initial page to allow instant back-button navigation. */\n\tpreloadInitialPage: boolean;\n\t/** Preload links when they are hovered, touched or focused. */\n\tpreloadHoveredLinks: boolean;\n\t/** Preload links when they enter the viewport. */\n\tpreloadVisibleLinks: VisibleLinkPreloadOptions;\n};\n\nexport type PluginInitOptions = Omit<PluginOptions, 'preloadVisibleLinks'> & {\n\t/** Preload links when they enter the viewport. */\n\tpreloadVisibleLinks: boolean | Partial<VisibleLinkPreloadOptions>;\n};\n\ntype PreloadOptions = {\n\t/** Priority of this preload: `true` for high, `false` for low. */\n\tpriority?: boolean;\n};\n\nexport default class SwupPreloadPlugin extends Plugin {\n\tname = 'SwupPreloadPlugin';\n\n\trequires = { swup: '>=4.5' };\n\n\tdefaults: PluginOptions = {\n\t\tthrottle: 5,\n\t\tpreloadInitialPage: true,\n\t\tpreloadHoveredLinks: true,\n\t\tpreloadVisibleLinks: {\n\t\t\tenabled: false,\n\t\t\tthreshold: 0.2,\n\t\t\tdelay: 500,\n\t\t\tcontainers: ['body'],\n\t\t\tignore: () => false\n\t\t}\n\t};\n\n\toptions: PluginOptions;\n\n\tprotected queue: Queue;\n\tprotected preloadObserver?: Observer;\n\tprotected preloadPromises = new Map<string, Promise<PageData | void>>();\n\n\tprotected mouseEnterDelegate?: DelegateEventUnsubscribe;\n\tprotected touchStartDelegate?: DelegateEventUnsubscribe;\n\tprotected focusDelegate?: DelegateEventUnsubscribe;\n\n\tconstructor(options: Partial<PluginInitOptions> = {}) {\n\t\tsuper();\n\n\t\t// Set all options except `preloadVisibleLinks` which is sanitized below\n\t\tconst { preloadVisibleLinks, ...otherOptions } = options;\n\t\tthis.options = { ...this.defaults, ...otherOptions };\n\n\t\t// Sanitize/merge `preloadVisibleLinks`` option\n\t\tif (typeof preloadVisibleLinks === 'object') {\n\t\t\tthis.options.preloadVisibleLinks = {\n\t\t\t\t...this.options.preloadVisibleLinks,\n\t\t\t\tenabled: true,\n\t\t\t\t...preloadVisibleLinks\n\t\t\t};\n\t\t} else {\n\t\t\tthis.options.preloadVisibleLinks.enabled = Boolean(preloadVisibleLinks);\n\t\t}\n\n\t\t// Bind public methods\n\t\tthis.preload = this.preload.bind(this);\n\n\t\t// Create global priority queue\n\t\tthis.queue = createQueue(this.options.throttle);\n\t}\n\n\tmount() {\n\t\tconst swup = this.swup;\n\n\t\tif (!swup.options.cache) {\n\t\t\tconsole.warn('SwupPreloadPlugin: swup cache needs to be enabled for preloading');\n\t\t\treturn;\n\t\t}\n\n\t\tswup.hooks.create('page:preload');\n\t\tswup.hooks.create('link:hover');\n\n\t\tswup.preload = this.preload;\n\t\tswup.preloadLinks = this.preloadLinks;\n\n\t\t// Inject custom promise whenever a page is loaded\n\t\tthis.replace('page:load', this.onPageLoad);\n\n\t\t// Preload links with [data-swup-preload] attr\n\t\tthis.preloadLinks();\n\t\tthis.on('page:view', () => this.preloadLinks());\n\n\t\t// Preload visible links in viewport\n\t\tif (this.options.preloadVisibleLinks.enabled) {\n\t\t\tthis.preloadVisibleLinks();\n\t\t\tthis.on('page:view', () => this.preloadVisibleLinks());\n\t\t}\n\n\t\t// Preload links on attention\n\t\tif (this.options.preloadHoveredLinks) {\n\t\t\tthis.preloadLinksOnAttention();\n\t\t}\n\n\t\t// Cache unmodified DOM of initial/current page\n\t\tif (this.options.preloadInitialPage) {\n\t\t\tthis.preload(getCurrentUrl());\n\t\t}\n\t}\n\n\tunmount() {\n\t\tthis.swup.preload = undefined;\n\t\tthis.swup.preloadLinks = undefined;\n\n\t\tthis.preloadPromises.clear();\n\n\t\tthis.mouseEnterDelegate?.destroy();\n\t\tthis.touchStartDelegate?.destroy();\n\t\tthis.focusDelegate?.destroy();\n\n\t\tthis.stopPreloadingVisibleLinks();\n\t}\n\n\t/**\n\t * Before core page load: return existing preload promise if available.\n\t */\n\tprotected onPageLoad: HookDefaultHandler<'page:load'> = (visit, args, defaultHandler) => {\n\t\tconst { url } = visit.to;\n\t\tif (url && this.preloadPromises.has(url)) {\n\t\t\treturn this.preloadPromises.get(url) as Promise<PageData>;\n\t\t}\n\t\treturn defaultHandler!(visit, args);\n\t};\n\n\t/**\n\t * When hovering over a link: preload the linked page with high priority.\n\t */\n\tprotected onMouseEnter: DelegateEventHandler = async (event) => {\n\t\t// Make sure mouseenter is only fired once even on links with nested html\n\t\tif (event.target !== event.delegateTarget) return;\n\n\t\t// Return early on devices that don't support hover\n\t\tif (!deviceSupportsHover()) return;\n\n\t\tconst el = event.delegateTarget;\n\t\tif (!isAnchorElement(el)) return;\n\n\t\t// Create temporary visit object for link:hover hook\n\t\tconst { url: to, hash } = Location.fromElement(el);\n\t\t// @ts-expect-error: createVisit is currently private, need to make this semi-public somehow\n\t\tconst visit = this.swup.createVisit({ to, hash, el, event });\n\n\t\tthis.swup.hooks.callSync('link:hover', visit, { el, event });\n\t\tthis.preload(el, { priority: true });\n\t};\n\n\t/**\n\t * When touching a link: preload the linked page with high priority.\n\t */\n\tprotected onTouchStart: DelegateEventHandler = (event) => {\n\t\t// Return early on devices that support hover\n\t\tif (deviceSupportsHover()) return;\n\n\t\tconst el = event.delegateTarget;\n\t\tif (!isAnchorElement(el)) return;\n\n\t\tthis.preload(el, { priority: true });\n\t};\n\n\t/**\n\t * When focussing a link: preload the linked page with high priority.\n\t */\n\tprotected onFocus: DelegateEventHandler = (event) => {\n\t\tconst el = event.delegateTarget;\n\t\tif (!isAnchorElement(el)) return;\n\n\t\tthis.preload(el, { priority: true });\n\t};\n\n\t/**\n\t * Preload links.\n\t *\n\t * The method accepts either:\n\t * - a URL or an array of URLs\n\t * - a link element or an array of link elements\n\t *\n\t * It returns either:\n\t * - a Promise resolving to the page data, if requesting a single page\n\t * - a Promise resolving to an array of page data, if requesting multiple pages\n\t */\n\tasync preload(url: string, options?: PreloadOptions): Promise<PageData | void>;\n\tasync preload(urls: string[], options?: PreloadOptions): Promise<(PageData | void)[]>;\n\tasync preload(el: AnchorElement, options?: PreloadOptions): Promise<PageData | void>;\n\tasync preload(els: AnchorElement[], options?: PreloadOptions): Promise<(PageData | void)[]>;\n\tasync preload(\n\t\tinput: string | AnchorElement,\n\t\toptions?: PreloadOptions\n\t): Promise<PageData | void>;\n\tasync preload(\n\t\tinput: string | string[] | AnchorElement | AnchorElement[],\n\t\toptions: PreloadOptions = {}\n\t): Promise<PageData | (PageData | void)[] | void> {\n\t\tlet url: string;\n\t\tlet el: AnchorElement | undefined;\n\t\tconst priority = options.priority ?? false;\n\n\t\t// Allow passing in array of urls or elements\n\t\tif (Array.isArray(input)) {\n\t\t\treturn Promise.all(input.map((link) => this.preload(link)));\n\t\t}\n\t\t// Allow passing in an anchor element\n\t\telse if (isAnchorElement(input)) {\n\t\t\tel = input;\n\t\t\t({ href: url } = Location.fromElement(input));\n\t\t}\n\t\t// Allow passing in a url\n\t\telse if (typeof input === 'string') {\n\t\t\turl = input;\n\t\t}\n\t\t// Disallow other types\n\t\telse {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return if no url passed in\n\t\tif (!url) return;\n\n\t\t// Already in cache? Return the data from the cache\n\t\tif (this.swup.cache.has(url)) {\n\t\t\treturn this.swup.cache.get(url);\n\t\t}\n\n\t\t// Already preloading? Return the existing promise\n\t\tif (this.preloadPromises.has(url)) {\n\t\t\treturn this.preloadPromises.get(url);\n\t\t}\n\n\t\t// Should we preload?\n\t\tif (!this.shouldPreload(url, { el })) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Queue the preload with either low or high priority\n\t\t// The actual preload will happen when a spot in the queue is available\n\t\tconst queuedPromise = new Promise<PageData | void>((resolve) => {\n\t\t\tthis.queue.add(() => {\n\t\t\t\tthis.performPreload(url)\n\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t.then((page) => resolve(page))\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tthis.queue.next();\n\t\t\t\t\t\tthis.preloadPromises.delete(url);\n\t\t\t\t\t});\n\t\t\t}, priority);\n\t\t});\n\n\t\tthis.preloadPromises.set(url, queuedPromise);\n\n\t\treturn queuedPromise;\n\t}\n\n\t/**\n\t * Preload any links on the current page manually marked for preloading.\n\t *\n\t * Links are marked for preloading by:\n\t * - adding a `data-swup-preload` attribute to the link itself\n\t * - adding a `data-swup-preload-all` attribute to a container of multiple links\n\t */\n\tpreloadLinks(): void {\n\t\twhenIdle(() => {\n\t\t\tconst selector = 'a[data-swup-preload], [data-swup-preload-all] a';\n\t\t\tconst links = Array.from(document.querySelectorAll<AnchorElement>(selector));\n\t\t\tlinks.forEach((el) => this.preload(el));\n\t\t});\n\t}\n\n\t/**\n\t * Register handlers for preloading on attention:\n\t *  - mouseenter\n\t *  - touchstart\n\t *  - focus\n\t */\n\tprotected preloadLinksOnAttention() {\n\t\tconst { swup } = this;\n\n\t\tconst { linkSelector: selector } = swup.options;\n\t\tconst opts = { passive: true, capture: true };\n\t\tthis.mouseEnterDelegate = swup.delegateEvent(\n\t\t\tselector,\n\t\t\t'mouseenter',\n\t\t\tthis.onMouseEnter,\n\t\t\topts\n\t\t);\n\t\tthis.touchStartDelegate = swup.delegateEvent(\n\t\t\tselector,\n\t\t\t'touchstart',\n\t\t\tthis.onTouchStart,\n\t\t\topts\n\t\t);\n\t\tthis.focusDelegate = swup.delegateEvent(selector, 'focus', this.onFocus, opts);\n\t}\n\n\t/**\n\t * Start observing links in the viewport for preloading.\n\t * Calling this repeatedly re-checks for links after DOM updates.\n\t */\n\tprotected preloadVisibleLinks(): void {\n\t\t// Scan DOM for new links on repeated calls\n\t\tif (this.preloadObserver) {\n\t\t\tthis.preloadObserver.update();\n\t\t\treturn;\n\t\t}\n\n\t\tconst { threshold, delay, containers } = this.options.preloadVisibleLinks;\n\t\tconst callback = (el: AnchorElement) => this.preload(el);\n\t\tconst filter = (el: AnchorElement) => {\n\t\t\t/** First, run the custom callback */\n\t\t\tif (this.options.preloadVisibleLinks.ignore(el)) return false;\n\t\t\t/** Second, check if it's a valid swup link */\n\t\t\tif (!el.matches(this.swup.options.linkSelector)) return false;\n\t\t\t/** Third, run all default checks */\n\t\t\tconst { href } = Location.fromElement(el);\n\t\t\treturn this.shouldPreload(href, { el });\n\t\t};\n\n\t\tthis.preloadObserver = createObserver({ threshold, delay, containers, callback, filter });\n\t\tthis.preloadObserver.start();\n\t}\n\n\t/**\n\t * Stop observing links in the viewport for preloading.\n\t */\n\tprotected stopPreloadingVisibleLinks(): void {\n\t\tif (this.preloadObserver) {\n\t\t\tthis.preloadObserver.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Check whether a URL and/or element should trigger a preload.\n\t */\n\tprotected shouldPreload(location: string, { el }: { el?: AnchorElement } = {}): boolean {\n\t\tconst { url, href } = Location.fromUrl(location);\n\n\t\t// Network too slow?\n\t\tif (!networkSupportsPreloading()) return false;\n\t\t// Already in cache?\n\t\tif (this.swup.cache.has(url)) return false;\n\t\t// Already preloading?\n\t\tif (this.preloadPromises.has(url)) return false;\n\t\t// Should be ignored anyway?\n\t\tif (this.swup.shouldIgnoreVisit(href, { el })) return false;\n\t\t// Special condition for links: points to current page?\n\t\tif (el && this.swup.resolveUrl(url) === this.swup.resolveUrl(getCurrentUrl())) return false;\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Perform the actual preload fetch and trigger the preload hook.\n\t */\n\tprotected async performPreload(href: string): Promise<PageData> {\n\t\tconst { url } = Location.fromUrl(href);\n\n\t\t// Create temporary visit object for page:preload hook\n\t\t// @ts-expect-error: createVisit is currently private, need to make this semi-public somehow\n\t\tconst visit = this.swup.createVisit({ to: url });\n\n\t\tconst page = await this.swup.hooks.call(\n\t\t\t'page:preload',\n\t\t\tvisit,\n\t\t\t{ url },\n\t\t\tasync (visit, args) => {\n\t\t\t\t// @ts-expect-error FetchOptions.visit is currently marked as internal\n\t\t\t\targs.page = await this.swup.fetchPage(href, { visit });\n\t\t\t\treturn args.page;\n\t\t\t}\n\t\t);\n\t\treturn page;\n\t}\n}\n","type QueueFunction = {\n\t(): void;\n\t__queued?: boolean;\n};\n\nexport type Queue = {\n\tadd: (fn: QueueFunction, highPriority?: boolean) => void;\n\tnext: () => void;\n};\n\nexport default function createQueue(limit: number = 1): Queue {\n\tconst qlow: QueueFunction[] = [];\n\tconst qhigh: QueueFunction[] = [];\n\tlet total = 0;\n\tlet running = 0;\n\n\tfunction add(fn: QueueFunction, highPriority: boolean = false): void {\n\t\t// Already added before?\n\t\tif (fn.__queued) {\n\t\t\t// Move from low to high-priority queue\n\t\t\tif (highPriority) {\n\t\t\t\tconst idx = qlow.indexOf(fn);\n\t\t\t\tif (idx >= 0) {\n\t\t\t\t\tconst removed = qlow.splice(idx, 1);\n\t\t\t\t\ttotal = total - removed.length;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Mark as processed\n\t\tfn.__queued = true;\n\t\t// Push to queue: high or low\n\t\t(highPriority ? qhigh : qlow).push(fn);\n\t\t// Increment total\n\t\ttotal++;\n\t\t// Initialize queue if first item\n\t\tif (total <= 1) {\n\t\t\trun();\n\t\t}\n\t}\n\n\tfunction next(): void {\n\t\trunning--; // make room for next\n\t\trun();\n\t}\n\n\tfunction run(): void {\n\t\tif (running < limit && total > 0) {\n\t\t\tconst fn = qhigh.shift() || qlow.shift() || (() => {});\n\t\t\tfn();\n\t\t\ttotal--;\n\t\t\trunning++; // is now WIP\n\t\t}\n\t}\n\n\treturn { add, next };\n}\n","import { Location } from 'swup';\n\nimport { AnchorElement } from './index.js';\nimport { whenIdle } from './util.js';\n\nexport type Observer = {\n\tstart: () => void;\n\tstop: () => void;\n\tupdate: () => void;\n};\n\nexport default function createObserver({\n\tthreshold,\n\tdelay,\n\tcontainers,\n\tcallback,\n\tfilter\n}: {\n\tthreshold: number;\n\tdelay: number;\n\tcontainers: string[];\n\tcallback: (el: AnchorElement) => void;\n\tfilter: (el: AnchorElement) => boolean;\n}): Observer {\n\tconst visibleLinks = new Map<string, Set<AnchorElement>>();\n\n\t// Create an observer to add/remove links when they enter the viewport\n\tconst observer = new IntersectionObserver(\n\t\t(entries) => {\n\t\t\tentries.forEach((entry) => {\n\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\tadd(entry.target as AnchorElement);\n\t\t\t\t} else {\n\t\t\t\t\tremove(entry.target as AnchorElement);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\t{ threshold }\n\t);\n\n\t// Preload link if it is still visible after a configurable timeout\n\tconst add = (el: AnchorElement) => {\n\t\tconst { href } = Location.fromElement(el);\n\t\tconst elements = visibleLinks.get(href) ?? new Set();\n\t\tvisibleLinks.set(href, elements);\n\t\telements.add(el);\n\n\t\tsetTimeout(() => {\n\t\t\tconst elements = visibleLinks.get(href);\n\t\t\tif (elements?.size) {\n\t\t\t\tcallback(el);\n\t\t\t\tobserver.unobserve(el);\n\t\t\t\telements.delete(el);\n\t\t\t}\n\t\t}, delay);\n\t};\n\n\t// Remove link from list of visible links\n\tconst remove = (el: AnchorElement) => {\n\t\tconst { href } = Location.fromElement(el);\n\t\tvisibleLinks.get(href)?.delete(el);\n\t};\n\n\t// Clear list of visible links\n\tconst clear = () => visibleLinks.clear();\n\n\t// Scan DOM for preloadable links and start observing their visibility\n\tconst observe = () => {\n\t\twhenIdle(() => {\n\t\t\tconst selector = containers.map((root) => `${root} a[*|href]`).join(', ');\n\t\t\tconst links = Array.from(document.querySelectorAll<AnchorElement>(selector));\n\t\t\tlinks.filter((el) => filter(el)).forEach((el) => observer.observe(el));\n\t\t});\n\t};\n\n\treturn {\n\t\tstart: () => observe(),\n\t\tstop: () => observer.disconnect(),\n\t\tupdate: () => (clear(), observe())\n\t};\n}\n"],"names":["deviceSupportsHover","window","matchMedia","matches","isAnchorElement","element","HTMLAnchorElement","SVGAElement","whenIdle","requestIdleCallback","cb","setTimeout","Plugin","constructor","options","super","_this","this","name","requires","swup","defaults","throttle","preloadInitialPage","preloadHoveredLinks","preloadVisibleLinks","enabled","threshold","delay","containers","ignore","queue","preloadObserver","preloadPromises","Map","mouseEnterDelegate","touchStartDelegate","focusDelegate","onPageLoad","visit","args","defaultHandler","url","to","has","get","onMouseEnter","event","target","delegateTarget","Promise","resolve","el","hash","Location","fromElement","createVisit","hooks","callSync","preload","priority","e","reject","onTouchStart","onFocus","otherOptions","Boolean","bind","limit","qlow","qhigh","total","running","run","shift","add","fn","highPriority","__queued","idx","indexOf","removed","splice","length","push","next","createQueue","mount","cache","create","preloadLinks","replace","on","preloadLinksOnAttention","getCurrentUrl","console","warn","unmount","undefined","clear","destroy","stopPreloadingVisibleLinks","input","_this2","Array","isArray","all","map","link","href","shouldPreload","queuedPromise","performPreload","catch","then","page","finally","delete","set","from","document","querySelectorAll","forEach","linkSelector","selector","opts","passive","capture","delegateEvent","update","callback","filter","visibleLinks","observer","IntersectionObserver","entries","entry","isIntersecting","remove","elements","Set","size","unobserve","observe","root","join","start","stop","disconnect","createObserver","location","fromUrl","navigator","connection","saveData","effectiveType","endsWith","networkSupportsPreloading","shouldIgnoreVisit","resolveUrl","_this3","call","fetchPage","_this3$swup$fetchPage"],"mappings":"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"}