summaryrefslogtreecommitdiff
path: root/node_modules/swup/src/Swup.ts
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2026-05-18 23:10:59 +0800
committerlittleblack111 <littleblack11111@gmail.com>2026-05-18 23:41:44 +0800
commitfc87c009806dcc98867f6b58efe29b042aa01dee (patch)
tree8f59b3f4a5b66e9dfef2d40c8d318e258a521228 /node_modules/swup/src/Swup.ts
parent3336b2356ee6152d9c6ae59bd9b87ccbc0958407 (diff)
node: updatemain
Diffstat (limited to 'node_modules/swup/src/Swup.ts')
-rw-r--r--node_modules/swup/src/Swup.ts382
1 files changed, 0 insertions, 382 deletions
diff --git a/node_modules/swup/src/Swup.ts b/node_modules/swup/src/Swup.ts
deleted file mode 100644
index 7fb76f06..00000000
--- a/node_modules/swup/src/Swup.ts
+++ /dev/null
@@ -1,382 +0,0 @@
-import { type DelegateEvent } from 'delegate-it';
-
-import version from './config/version.js';
-
-import { delegateEvent, getCurrentUrl, Location, updateHistoryRecord } from './helpers.js';
-import { type DelegateEventUnsubscribe } from './helpers/delegateEvent.js';
-
-import { Cache } from './modules/Cache.js';
-import { Classes } from './modules/Classes.js';
-import { type Visit, createVisit } from './modules/Visit.js';
-import { Hooks, type HookName, type HookInitOptions } from './modules/Hooks.js';
-import { getAnchorElement } from './modules/getAnchorElement.js';
-import { awaitAnimations } from './modules/awaitAnimations.js';
-import { navigate, performNavigation, type NavigationToSelfAction } from './modules/navigate.js';
-import { fetchPage } from './modules/fetchPage.js';
-import { animatePageOut } from './modules/animatePageOut.js';
-import { replaceContent } from './modules/replaceContent.js';
-import { scrollToContent } from './modules/scrollToContent.js';
-import { animatePageIn } from './modules/animatePageIn.js';
-import { renderPage } from './modules/renderPage.js';
-import { use, unuse, findPlugin, type Plugin } from './modules/plugins.js';
-import { isSameResolvedUrl, resolveUrl } from './modules/resolveUrl.js';
-import { nextTick } from './utils.js';
-import { type HistoryState } from './helpers/history.js';
-
-/** Options for customizing swup's behavior. */
-export type Options = {
- /** Whether history visits are animated. Default: `false` */
- animateHistoryBrowsing: boolean;
- /** Selector for detecting animation timing. Default: `[class*="transition-"]` */
- animationSelector: string | false;
- /** Elements on which to add animation classes. Default: `html` element */
- animationScope: 'html' | 'containers';
- /** Enable in-memory page cache. Default: `true` */
- cache: boolean;
- /** Content containers to be replaced on page visits. Default: `['#swup']` */
- containers: string[];
- /** Callback for ignoring visits. Receives the element and event that triggered the visit. */
- ignoreVisit: (url: string, { el, event }: { el?: Element; event?: Event }) => boolean;
- /** Selector for links that trigger visits. Default: `'a[href]'` */
- linkSelector: string;
- /** How swup handles links to the same page. Default: `scroll` */
- linkToSelf: NavigationToSelfAction;
- /** Enable native animations using the View Transitions API. */
- native: boolean;
- /** Hook handlers to register. */
- hooks: Partial<HookInitOptions>;
- /** Plugins to register on startup. */
- plugins: Plugin[];
- /** Custom headers sent along with fetch requests. */
- requestHeaders: Record<string, string>;
- /** Rewrite URLs before loading them. */
- resolveUrl: (url: string) => string;
- /** Callback for telling swup to ignore certain popstate events. */
- skipPopStateHandling: (event: PopStateEvent) => boolean;
- /** Request timeout in milliseconds. */
- timeout: number;
-};
-
-const defaults: Options = {
- animateHistoryBrowsing: false,
- animationSelector: '[class*="transition-"]',
- animationScope: 'html',
- cache: true,
- containers: ['#swup'],
- hooks: {},
- ignoreVisit: (url, { el } = {}) => !!el?.closest('[data-no-swup]'),
- linkSelector: 'a[href]',
- linkToSelf: 'scroll',
- native: false,
- plugins: [],
- resolveUrl: (url) => url,
- requestHeaders: {
- 'X-Requested-With': 'swup',
- 'Accept': 'text/html, application/xhtml+xml'
- },
- skipPopStateHandling: (event) => (event.state as HistoryState)?.source !== 'swup',
- timeout: 0
-};
-
-/** Swup page transition library. */
-export default class Swup {
- /** Library version */
- readonly version: string = version;
- /** Options passed into the instance */
- options: Options;
- /** Default options before merging user options */
- readonly defaults: Options = defaults;
- /** Registered plugin instances */
- plugins: Plugin[] = [];
- /** Data about the current visit */
- visit: Visit;
- /** Cache instance */
- readonly cache: Cache;
- /** Hook registry */
- readonly hooks: Hooks;
- /** Animation class manager */
- readonly classes: Classes;
- /** Location of the currently visible page */
- location: Location = Location.fromUrl(window.location.href);
- /** URL of the currently visible page @deprecated Use swup.location.url instead */
- get currentPageUrl(): string {
- return this.location.url;
- }
- /** Index of the current history entry */
- protected currentHistoryIndex: number;
- /** Delegated event subscription handle */
- protected clickDelegate?: DelegateEventUnsubscribe;
- /** Navigation status */
- protected navigating: boolean = false;
- /** Run anytime a visit ends */
- protected onVisitEnd?: () => Promise<unknown>;
-
- /** Install a plugin */
- use = use;
- /** Uninstall a plugin */
- unuse = unuse;
- /** Find a plugin by name or instance */
- findPlugin = findPlugin;
-
- /** Log a message. Has no effect unless debug plugin is installed */
- log: (message: string, context?: unknown) => void = () => {};
-
- /** Navigate to a new URL */
- navigate = navigate;
- /** Actually perform a navigation */
- protected performNavigation = performNavigation;
- /** Create a new context for this visit */
- protected createVisit = createVisit;
- /** Register a delegated event listener */
- delegateEvent = delegateEvent;
- /** Fetch a page from the server */
- fetchPage = fetchPage;
- /** Resolve when animations on the page finish */
- awaitAnimations = awaitAnimations;
- protected renderPage = renderPage;
- /** Replace the content after page load */
- replaceContent = replaceContent;
- protected animatePageIn = animatePageIn;
- protected animatePageOut = animatePageOut;
- protected scrollToContent = scrollToContent;
- /** Find the anchor element for a given hash */
- getAnchorElement = getAnchorElement;
-
- /** Get the current page URL */
- getCurrentUrl = getCurrentUrl;
- /** Resolve a URL to its final location */
- resolveUrl = resolveUrl;
- /** Check if two URLs resolve to the same location */
- protected isSameResolvedUrl = isSameResolvedUrl;
-
- constructor(options: Partial<Options> = {}) {
- // Merge defaults and options
- this.options = { ...this.defaults, ...options };
-
- this.handleLinkClick = this.handleLinkClick.bind(this);
- this.handlePopState = this.handlePopState.bind(this);
-
- this.cache = new Cache(this);
- this.classes = new Classes(this);
- this.hooks = new Hooks(this);
- this.visit = this.createVisit({ to: '' });
-
- this.currentHistoryIndex = (window.history.state as HistoryState)?.index ?? 1;
-
- this.enable();
- }
-
- /** Enable this instance, adding listeners and classnames. */
- async enable() {
- // Add event listener
- const { linkSelector } = this.options;
- this.clickDelegate = this.delegateEvent(linkSelector, 'click', this.handleLinkClick);
-
- window.addEventListener('popstate', this.handlePopState);
-
- // Set scroll restoration to manual if animating history visits
- if (this.options.animateHistoryBrowsing) {
- window.history.scrollRestoration = 'manual';
- }
-
- // Initial save to cache
- if (this.options.cache) {
- // Disabled to avoid caching modified dom state: logic moved to preload plugin
- // https://github.com/swup/swup/issues/475
- }
-
- // Sanitize/check native option
- this.options.native = this.options.native && !!document.startViewTransition;
-
- // Mount plugins
- this.options.plugins.forEach((plugin) => this.use(plugin));
-
- // Install user hooks
- for (const [key, handler] of Object.entries(this.options.hooks)) {
- // Build hook options from modifier suffix: 'content:replace.before' => { before: true }
- const [hook, modifiers] = this.hooks.parseName(key as HookName);
- // @ts-expect-error: object.entries() does not preserve key/value types
- this.hooks.on(hook, handler, modifiers);
- }
-
- // Create initial history record
- if ((window.history.state as HistoryState)?.source !== 'swup') {
- updateHistoryRecord(null, { index: this.currentHistoryIndex });
- }
-
- // Give consumers a chance to hook into enable
- await nextTick();
-
- // Trigger enable hook
- await this.hooks.call('enable', undefined, undefined, () => {
- const html = document.documentElement;
- html.classList.add('swup-enabled');
- html.classList.toggle('swup-native', this.options.native);
- });
- }
-
- /** Disable this instance, removing listeners and classnames. */
- async destroy() {
- // remove delegated listener
- this.clickDelegate!.destroy();
-
- // remove popstate listener
- window.removeEventListener('popstate', this.handlePopState);
-
- // empty cache
- this.cache.clear();
-
- // unmount plugins
- this.options.plugins.forEach((plugin) => this.unuse(plugin));
-
- // trigger disable hook
- await this.hooks.call('disable', undefined, undefined, () => {
- const html = document.documentElement;
- html.classList.remove('swup-enabled');
- html.classList.remove('swup-native');
- });
-
- // remove handlers
- this.hooks.clear();
- }
-
- /** Determine if a visit should be ignored by swup, based on URL or trigger element. */
- shouldIgnoreVisit(href: string, { el, event }: { el?: Element; event?: Event } = {}) {
- const { origin, url, hash } = Location.fromUrl(href);
-
- // Ignore if the new origin doesn't match the current one
- if (origin !== window.location.origin) {
- return true;
- }
-
- // Ignore if the link/form would open a new window (or none at all)
- if (el && this.triggerWillOpenNewWindow(el)) {
- return true;
- }
-
- // Ignore if the visit should be ignored as per user options
- if (this.options.ignoreVisit(url + hash, { el, event })) {
- return true;
- }
-
- // Finally, allow the visit
- return false;
- }
-
- protected handleLinkClick(event: DelegateEvent<MouseEvent>) {
- const el = event.delegateTarget as HTMLAnchorElement;
- const { href, url, hash } = Location.fromElement(el);
-
- // Exit early if the link should be ignored
- if (this.shouldIgnoreVisit(href, { el, event })) {
- return;
- }
-
- // Ignore if swup is currently navigating towards the link's URL
- if (this.navigating && url === this.visit.to.url) {
- event.preventDefault();
- return;
- }
-
- const visit = this.createVisit({ to: url, hash, el, event });
-
- // Exit early if control key pressed
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
- this.hooks.callSync('link:newtab', visit, { href });
- return;
- }
-
- // Exit early if other than left mouse button
- if (event.button !== 0) {
- return;
- }
-
- this.hooks.callSync('link:click', visit, { el, event }, () => {
- const from = visit.from.url ?? '';
-
- event.preventDefault();
-
- // Handle links to the same page
- if (!url || url === from) {
- if (hash) {
- // With hash: scroll to anchor
- this.hooks.callSync('link:anchor', visit, { hash }, () => {
- updateHistoryRecord(url + hash);
- this.scrollToContent(visit);
- });
- } else {
- // Without hash: scroll to top or load/reload page
- this.hooks.callSync('link:self', visit, undefined, () => {
- if (this.options.linkToSelf === 'navigate') {
- this.performNavigation(visit);
- } else {
- updateHistoryRecord(url);
- this.scrollToContent(visit);
- }
- });
- }
- return;
- }
-
- // Exit early if the resolved path hasn't changed
- if (this.isSameResolvedUrl(url, from)) {
- return;
- }
-
- // Finally, proceed with loading the page
- this.performNavigation(visit);
- });
- }
-
- protected handlePopState(event: PopStateEvent) {
- const href: string = (event.state as HistoryState)?.url ?? window.location.href;
-
- // Exit early if this event should be ignored
- if (this.options.skipPopStateHandling(event)) {
- return;
- }
-
- // Exit early if the resolved path hasn't changed
- if (this.isSameResolvedUrl(getCurrentUrl(), this.location.url)) {
- return;
- }
-
- const { url, hash } = Location.fromUrl(href);
-
- const visit = this.createVisit({ to: url, hash, event });
-
- // Mark as history visit
- visit.history.popstate = true;
-
- // Determine direction of history visit
- const index = (event.state as HistoryState)?.index ?? 0;
- if (index && index !== this.currentHistoryIndex) {
- const direction = index - this.currentHistoryIndex > 0 ? 'forwards' : 'backwards';
- visit.history.direction = direction;
- this.currentHistoryIndex = index;
- }
-
- // Disable animation & scrolling for history visits
- visit.animation.animate = false;
- visit.scroll.reset = false;
- visit.scroll.target = false;
-
- // Animated history visit: re-enable animation & scroll reset
- if (this.options.animateHistoryBrowsing) {
- visit.animation.animate = true;
- visit.scroll.reset = true;
- }
-
- this.hooks.callSync('history:popstate', visit, { event }, () => {
- this.performNavigation(visit);
- });
- }
-
- /** Determine whether an element will open a new tab when clicking/activating. */
- protected triggerWillOpenNewWindow(triggerEl: Element) {
- if (triggerEl.matches('[download], [target="_blank"]')) {
- return true;
- }
- return false;
- }
-}