swup 3.1.0 → 4.0.0-rc.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Swup.cjs +1 -1
- package/dist/Swup.cjs.map +1 -1
- package/dist/Swup.modern.js +1 -1
- package/dist/Swup.modern.js.map +1 -1
- package/dist/Swup.module.js +1 -1
- package/dist/Swup.module.js.map +1 -1
- package/dist/Swup.umd.js +1 -1
- package/dist/Swup.umd.js.map +1 -1
- package/dist/types/Swup.d.ts +20 -20
- package/dist/types/helpers/delegateEvent.d.ts +4 -2
- package/dist/types/helpers/fetch.d.ts +2 -2
- package/dist/types/helpers.d.ts +10 -10
- package/dist/types/index.d.ts +5 -5
- package/dist/types/modules/Cache.d.ts +2 -2
- package/dist/types/modules/__test__/fetchPage.test.d.ts +1 -0
- package/dist/types/modules/destroy.d.ts +2 -0
- package/dist/types/modules/enable.d.ts +2 -0
- package/dist/types/modules/enterPage.d.ts +2 -2
- package/dist/types/modules/events.d.ts +6 -6
- package/dist/types/modules/fetchPage.d.ts +3 -3
- package/dist/types/modules/getAnchorElement.d.ts +0 -7
- package/dist/types/modules/getAnimationPromises.d.ts +1 -1
- package/dist/types/modules/getPageData.d.ts +2 -2
- package/dist/types/modules/handleLinkToSamePage.d.ts +2 -0
- package/dist/types/modules/isSameResolvedUrl.d.ts +8 -0
- package/dist/types/modules/leavePage.d.ts +2 -2
- package/dist/types/modules/linkClickHandler.d.ts +3 -0
- package/dist/types/modules/loadPage.d.ts +2 -5
- package/dist/types/modules/off.d.ts +3 -0
- package/dist/types/modules/on.d.ts +5 -0
- package/dist/types/modules/plugins.d.ts +1 -1
- package/dist/types/modules/popStateHandler.d.ts +2 -0
- package/dist/types/modules/renderPage.d.ts +2 -2
- package/dist/types/modules/resolveUrl.d.ts +7 -0
- package/dist/types/modules/shouldIgnoreVisit.d.ts +4 -0
- package/dist/types/modules/transitions.d.ts +1 -1
- package/dist/types/modules/triggerEvent.d.ts +3 -0
- package/dist/types/modules/triggerWillOpenNewWindow.d.ts +2 -0
- package/dist/types/modules/updateTransition.d.ts +2 -0
- package/dist/types/utils.d.ts +1 -1
- package/package.json +8 -5
- package/readme.md +30 -12
- package/src/Swup.ts +115 -143
- package/src/__test__/index.test.ts +6 -1
- package/src/helpers/Location.ts +10 -7
- package/src/helpers/__test__/matchPath.test.ts +54 -0
- package/src/helpers/delegateEvent.ts +1 -0
- package/src/helpers/matchPath.ts +22 -0
- package/src/helpers.ts +2 -4
- package/src/index.ts +7 -4
- package/src/modules/Cache.ts +43 -33
- package/src/modules/Context.ts +91 -0
- package/src/modules/Hooks.ts +393 -0
- package/src/modules/__test__/cache.test.ts +142 -0
- package/src/modules/__test__/hooks.test.ts +192 -0
- package/src/modules/enterPage.ts +19 -17
- package/src/modules/fetchPage.ts +74 -29
- package/src/modules/getAnchorElement.ts +8 -4
- package/src/modules/getAnimationPromises.ts +66 -75
- package/src/modules/leavePage.ts +22 -20
- package/src/modules/loadPage.ts +72 -54
- package/src/modules/renderPage.ts +41 -32
- package/src/modules/replaceContent.ts +26 -17
- package/src/utils/index.ts +24 -3
- package/src/helpers/fetch.ts +0 -33
- package/src/helpers/getDataFromHtml.ts +0 -39
- package/src/helpers/markSwupElements.ts +0 -16
- package/src/modules/__test__/events.test.ts +0 -72
- package/src/modules/events.ts +0 -92
- package/src/modules/getPageData.ts +0 -24
- package/src/modules/transitions.ts +0 -10
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import Swup from '../Swup';
|
|
2
|
+
export type EventType = 'animationInDone' | 'animationInStart' | 'animationOutDone' | 'animationOutStart' | 'animationSkipped' | 'clickLink' | 'contentReplaced' | 'disabled' | 'enabled' | 'openPageInNewTab' | 'pageLoaded' | 'pageRetrievedFromCache' | 'pageView' | 'popState' | 'samePage' | 'samePageWithHash' | 'serverError' | 'transitionStart' | 'transitionEnd' | 'willReplaceContent';
|
|
3
|
+
export type Handler = (event?: Event) => void;
|
|
4
|
+
export type Handlers = Record<EventType, Handler[]>;
|
|
5
|
+
export declare const on: (this: Swup, event: EventType, handler: Handler) => void;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './utils/index
|
|
1
|
+
export * from './utils/index';
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swup",
|
|
3
3
|
"amdName": "Swup",
|
|
4
|
-
"version": "
|
|
5
|
-
"description": "
|
|
4
|
+
"version": "4.0.0-rc.14",
|
|
5
|
+
"description": "Versatile and extensible page transition library for server-side rendered websites",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"source": "./src/Swup.ts",
|
|
8
8
|
"main": "./dist/Swup.cjs",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"test": "npm run test:unit && npm run test:e2e",
|
|
35
35
|
"test:ci": "npm run test:unit && npm run test:e2e:ci",
|
|
36
36
|
"test:unit": "vitest run --config ./vitest/vitest.config.ts",
|
|
37
|
+
"test:unit:watch": "vitest --config ./vitest/vitest.config.ts",
|
|
37
38
|
"test:e2e": "start-server-and-test test:e2e:start 8274 cy:run",
|
|
38
39
|
"test:e2e:ci": "start-server-and-test test:e2e:start 8274 cy:run:record",
|
|
39
40
|
"test:e2e:dev": "start-server-and-test test:e2e:start 8274 cy:open",
|
|
@@ -59,7 +60,8 @@
|
|
|
59
60
|
],
|
|
60
61
|
"dependencies": {
|
|
61
62
|
"delegate-it": "^6.0.0",
|
|
62
|
-
"opencollective-postinstall": "^2.0.2"
|
|
63
|
+
"opencollective-postinstall": "^2.0.2",
|
|
64
|
+
"path-to-regexp": "^6.2.1"
|
|
63
65
|
},
|
|
64
66
|
"devDependencies": {
|
|
65
67
|
"@babel/preset-typescript": "^7.18.6",
|
|
@@ -70,11 +72,12 @@
|
|
|
70
72
|
"http-server": "^14.1.1",
|
|
71
73
|
"husky": "^8.0.0",
|
|
72
74
|
"istanbul-lib-coverage": "^3.2.0",
|
|
75
|
+
"jsdom": "^22.1.0",
|
|
73
76
|
"microbundle": "^0.15.0",
|
|
74
77
|
"nyc": "^15.1.0",
|
|
75
78
|
"prettier": "^2.8.2",
|
|
76
|
-
"start-server-and-test": "^
|
|
77
|
-
"vitest": "^0.
|
|
79
|
+
"start-server-and-test": "^2.0.0",
|
|
80
|
+
"vitest": "^0.31.2"
|
|
78
81
|
},
|
|
79
82
|
"collective": {
|
|
80
83
|
"type": "opencollective",
|
package/readme.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
# Swup
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Versatile and extensible page transition library for server-side rendered websites
|
|
20
20
|
|
|
21
21
|
[Features](#features) •
|
|
22
22
|
[Documentation](https://swup.js.org/getting-started) •
|
|
@@ -26,21 +26,39 @@ Complete, flexible, extensible, and easy-to-use page transition library for your
|
|
|
26
26
|
|
|
27
27
|
## Overview
|
|
28
28
|
|
|
29
|
-
Swup
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
Swup adds page transitions to server-side rendered websites. It manages the complete lifecycle of a
|
|
30
|
+
page visit by intercepting link clicks, loading the new page in the background and smoothly
|
|
31
|
+
transitioning between the old and new content.
|
|
32
32
|
|
|
33
|
-
Its goal is to make
|
|
34
|
-
|
|
33
|
+
Its goal is to make it effortless to add page transitions to a site, while providing lots of other
|
|
34
|
+
quality-of-life improvements.
|
|
35
35
|
|
|
36
36
|
## Features
|
|
37
37
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
38
|
+
- ✏️ Works out of the box with [minimal markup](https://swup.js.org/getting-started/example/)
|
|
39
|
+
- ✨ Auto-detects [CSS transitions](https://swup.js.org/getting-started/how-it-works/) for perfect timing
|
|
40
|
+
- 🔗 Updates URLs and preserves native [browser history](https://swup.js.org/options/#animatehistorybrowsing)
|
|
41
|
+
- 🏓 Manages scroll position between pages and anchor jump links
|
|
42
|
+
- 🚀 Uses a [cache](https://swup.js.org/api/cache/) to speed up subsequent page loads
|
|
43
|
+
- 📡 Offers [hooks](https://swup.js.org/hooks/) to customize and extend the page load lifecycle
|
|
44
|
+
- 🔌 Has a powerful [plugin system](https://swup.js.org/plugins/) and many official and third-party plugins
|
|
45
|
+
- 🎨 Provides ready-to-go [themes](https://swup.js.org/themes/) to get started quickly
|
|
46
|
+
|
|
47
|
+
## Plugins
|
|
48
|
+
|
|
49
|
+
Swup is small by design. Extended features can be added via [plugins](https://swup.js.org/plugins/):
|
|
50
|
+
|
|
51
|
+
- Display a [progress bar](https://swup.js.org/plugins/progress-plugin/) while loading
|
|
52
|
+
- Enable [smooth scrolling](https://swup.js.org/plugins/scroll-plugin/) between visits
|
|
53
|
+
- Update [meta tags and stylesheets](https://swup.js.org/plugins/head-plugin/) after page loads
|
|
54
|
+
- Add support for [preloading pages](https://swup.js.org/plugins/preload-plugin/) in the background
|
|
55
|
+
- Improve [accessibility](https://swup.js.org/plugins/a11y-plugin/) for screen readers
|
|
56
|
+
- Perform your [animations in JS](https://swup.js.org/plugins/js-plugin/) instead of CSS transitions
|
|
57
|
+
- Animate [form submissions](https://swup.js.org/plugins/forms-plugin/)
|
|
58
|
+
- Get help in [debug mode](https://swup.js.org/plugins/debug-plugin/)
|
|
59
|
+
|
|
60
|
+
Check out the list of [all official plugins](https://swup.js.org/plugins/) as well as
|
|
61
|
+
[third-party integrations](https://swup.js.org/third-party-integrations/).
|
|
44
62
|
|
|
45
63
|
## Examples
|
|
46
64
|
|
package/src/Swup.ts
CHANGED
|
@@ -7,26 +7,22 @@ import {
|
|
|
7
7
|
delegateEvent,
|
|
8
8
|
getCurrentUrl,
|
|
9
9
|
Location,
|
|
10
|
-
markSwupElements,
|
|
11
10
|
updateHistoryRecord
|
|
12
11
|
} from './helpers.js';
|
|
13
12
|
import { Unsubscribe } from './helpers/delegateEvent.js';
|
|
14
13
|
|
|
15
14
|
import { Cache } from './modules/Cache.js';
|
|
15
|
+
import { Context, createContext } from './modules/Context.js';
|
|
16
16
|
import { enterPage } from './modules/enterPage.js';
|
|
17
17
|
import { getAnchorElement } from './modules/getAnchorElement.js';
|
|
18
18
|
import { getAnimationPromises } from './modules/getAnimationPromises.js';
|
|
19
|
-
import { getPageData } from './modules/getPageData.js';
|
|
20
19
|
import { fetchPage } from './modules/fetchPage.js';
|
|
21
20
|
import { leavePage } from './modules/leavePage.js';
|
|
22
21
|
import { HistoryAction, loadPage, performPageLoad } from './modules/loadPage.js';
|
|
23
22
|
import { replaceContent } from './modules/replaceContent.js';
|
|
24
|
-
import {
|
|
23
|
+
import { Handler, HookName, Hooks } from './modules/Hooks.js';
|
|
25
24
|
import { use, unuse, findPlugin, Plugin } from './modules/plugins.js';
|
|
26
25
|
import { renderPage } from './modules/renderPage.js';
|
|
27
|
-
import { updateTransition, shouldSkipTransition } from './modules/transitions.js';
|
|
28
|
-
|
|
29
|
-
import { queryAll } from './utils.js';
|
|
30
26
|
|
|
31
27
|
export type Transition = {
|
|
32
28
|
from?: string;
|
|
@@ -52,47 +48,21 @@ export type Options = {
|
|
|
52
48
|
};
|
|
53
49
|
|
|
54
50
|
export default class Swup {
|
|
55
|
-
version = version;
|
|
56
|
-
|
|
57
|
-
_handlers: Handlers = {
|
|
58
|
-
animationInDone: [],
|
|
59
|
-
animationInStart: [],
|
|
60
|
-
animationOutDone: [],
|
|
61
|
-
animationOutStart: [],
|
|
62
|
-
animationSkipped: [],
|
|
63
|
-
clickLink: [],
|
|
64
|
-
contentReplaced: [],
|
|
65
|
-
disabled: [],
|
|
66
|
-
enabled: [],
|
|
67
|
-
openPageInNewTab: [],
|
|
68
|
-
pageLoaded: [],
|
|
69
|
-
pageRetrievedFromCache: [],
|
|
70
|
-
pageView: [],
|
|
71
|
-
popState: [],
|
|
72
|
-
samePage: [],
|
|
73
|
-
samePageWithHash: [],
|
|
74
|
-
serverError: [],
|
|
75
|
-
transitionStart: [],
|
|
76
|
-
transitionEnd: [],
|
|
77
|
-
willReplaceContent: []
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// variable for anchor to scroll to after render
|
|
81
|
-
scrollToElement: string | null = null;
|
|
51
|
+
version: string = version;
|
|
82
52
|
// variable for save options
|
|
83
53
|
options: Options;
|
|
84
54
|
// running plugin instances
|
|
85
55
|
plugins: Plugin[] = [];
|
|
86
|
-
//
|
|
87
|
-
|
|
56
|
+
// context data
|
|
57
|
+
context: Context;
|
|
88
58
|
// cache instance
|
|
89
59
|
cache: Cache;
|
|
90
|
-
//
|
|
91
|
-
|
|
60
|
+
// hook registry
|
|
61
|
+
hooks: Hooks;
|
|
92
62
|
// variable for keeping event listeners from "delegate"
|
|
93
63
|
delegatedListeners: DelegatedListeners = {};
|
|
94
|
-
//
|
|
95
|
-
|
|
64
|
+
// allows us to compare the current and new path inside popStateHandler
|
|
65
|
+
currentPageUrl = getCurrentUrl();
|
|
96
66
|
|
|
97
67
|
loadPage = loadPage;
|
|
98
68
|
performPageLoad = performPageLoad;
|
|
@@ -100,14 +70,8 @@ export default class Swup {
|
|
|
100
70
|
renderPage = renderPage;
|
|
101
71
|
replaceContent = replaceContent;
|
|
102
72
|
enterPage = enterPage;
|
|
103
|
-
triggerEvent = triggerEvent;
|
|
104
73
|
delegateEvent = delegateEvent;
|
|
105
|
-
on = on;
|
|
106
|
-
off = off;
|
|
107
|
-
updateTransition = updateTransition;
|
|
108
|
-
shouldSkipTransition = shouldSkipTransition;
|
|
109
74
|
getAnimationPromises = getAnimationPromises;
|
|
110
|
-
getPageData = getPageData;
|
|
111
75
|
fetchPage = fetchPage;
|
|
112
76
|
getAnchorElement = getAnchorElement;
|
|
113
77
|
log: (message: string, context?: any) => void = () => {}; // here so it can be used by plugins
|
|
@@ -116,6 +80,7 @@ export default class Swup {
|
|
|
116
80
|
findPlugin = findPlugin;
|
|
117
81
|
getCurrentUrl = getCurrentUrl;
|
|
118
82
|
cleanupAnimationClasses = cleanupAnimationClasses;
|
|
83
|
+
createContext = createContext;
|
|
119
84
|
|
|
120
85
|
defaults: Options = {
|
|
121
86
|
animateHistoryBrowsing: false,
|
|
@@ -137,28 +102,34 @@ export default class Swup {
|
|
|
137
102
|
// Merge defaults and options
|
|
138
103
|
this.options = { ...this.defaults, ...options };
|
|
139
104
|
|
|
140
|
-
this.
|
|
105
|
+
this.linkClickHandler = this.linkClickHandler.bind(this);
|
|
106
|
+
this.popStateHandler = this.popStateHandler.bind(this);
|
|
141
107
|
|
|
142
108
|
this.cache = new Cache(this);
|
|
109
|
+
this.hooks = new Hooks(this);
|
|
110
|
+
this.context = this.createContext({ to: undefined });
|
|
111
|
+
|
|
112
|
+
if (!this.checkRequirements()) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
143
115
|
|
|
144
116
|
this.enable();
|
|
145
117
|
}
|
|
146
118
|
|
|
147
|
-
|
|
148
|
-
// Check for Promise support
|
|
119
|
+
checkRequirements() {
|
|
149
120
|
if (typeof Promise === 'undefined') {
|
|
150
121
|
console.warn('Promise is not supported');
|
|
151
|
-
return;
|
|
122
|
+
return false;
|
|
152
123
|
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
153
126
|
|
|
127
|
+
async enable() {
|
|
154
128
|
// Add event listeners
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
'click',
|
|
158
|
-
this.linkClickHandler.bind(this)
|
|
159
|
-
);
|
|
129
|
+
const { linkSelector } = this.options;
|
|
130
|
+
this.delegatedListeners.click = delegateEvent(linkSelector, 'click', this.linkClickHandler);
|
|
160
131
|
|
|
161
|
-
window.addEventListener('popstate', this.
|
|
132
|
+
window.addEventListener('popstate', this.popStateHandler);
|
|
162
133
|
|
|
163
134
|
// Initial save to cache
|
|
164
135
|
if (this.options.cache) {
|
|
@@ -166,9 +137,6 @@ export default class Swup {
|
|
|
166
137
|
// https://github.com/swup/swup/issues/475
|
|
167
138
|
}
|
|
168
139
|
|
|
169
|
-
// Mark swup blocks in html
|
|
170
|
-
markSwupElements(document.documentElement, this.options.containers);
|
|
171
|
-
|
|
172
140
|
// Mount plugins
|
|
173
141
|
this.options.plugins.forEach((plugin) => this.use(plugin));
|
|
174
142
|
|
|
@@ -176,43 +144,36 @@ export default class Swup {
|
|
|
176
144
|
updateHistoryRecord();
|
|
177
145
|
|
|
178
146
|
// Trigger enabled event
|
|
179
|
-
this.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
147
|
+
await this.hooks.trigger('enabled', undefined, () => {
|
|
148
|
+
// Add swup-enabled class to html tag
|
|
149
|
+
document.documentElement.classList.add('swup-enabled');
|
|
150
|
+
});
|
|
183
151
|
|
|
184
152
|
// Trigger page view event
|
|
185
|
-
this.
|
|
153
|
+
await this.hooks.trigger('pageView', { url: this.currentPageUrl, title: document.title });
|
|
186
154
|
}
|
|
187
155
|
|
|
188
|
-
destroy() {
|
|
156
|
+
async destroy() {
|
|
189
157
|
// remove delegated listeners
|
|
190
158
|
this.delegatedListeners.click!.destroy();
|
|
191
159
|
|
|
192
160
|
// remove popstate listener
|
|
193
|
-
window.removeEventListener('popstate', this.
|
|
161
|
+
window.removeEventListener('popstate', this.popStateHandler);
|
|
194
162
|
|
|
195
163
|
// empty cache
|
|
196
|
-
this.cache.
|
|
164
|
+
this.cache.clear();
|
|
197
165
|
|
|
198
166
|
// unmount plugins
|
|
199
|
-
this.options.plugins.forEach((plugin) =>
|
|
200
|
-
this.unuse(plugin);
|
|
201
|
-
});
|
|
167
|
+
this.options.plugins.forEach((plugin) => this.unuse(plugin));
|
|
202
168
|
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
169
|
+
// trigger disable event
|
|
170
|
+
await this.hooks.trigger('disabled', undefined, () => {
|
|
171
|
+
// remove swup-enabled class from html tag
|
|
172
|
+
document.documentElement.classList.remove('swup-enabled');
|
|
206
173
|
});
|
|
207
174
|
|
|
208
175
|
// remove handlers
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
// trigger disable event
|
|
212
|
-
this.triggerEvent('disabled');
|
|
213
|
-
|
|
214
|
-
// remove swup-enabled class from html tag
|
|
215
|
-
document.documentElement.classList.remove('swup-enabled');
|
|
176
|
+
this.hooks.clear();
|
|
216
177
|
}
|
|
217
178
|
|
|
218
179
|
shouldIgnoreVisit(href: string, { el, event }: { el?: Element; event?: Event } = {}) {
|
|
@@ -238,17 +199,36 @@ export default class Swup {
|
|
|
238
199
|
}
|
|
239
200
|
|
|
240
201
|
linkClickHandler(event: DelegateEvent<MouseEvent>) {
|
|
241
|
-
const
|
|
242
|
-
const { href, url, hash } = Location.fromElement(
|
|
202
|
+
const el = event.delegateTarget as HTMLAnchorElement;
|
|
203
|
+
const { href, url, hash } = Location.fromElement(el);
|
|
204
|
+
|
|
205
|
+
// Get the transition name, if specified
|
|
206
|
+
const transition = el.getAttribute('data-swup-transition') || undefined;
|
|
207
|
+
|
|
208
|
+
// Get the history action, if specified
|
|
209
|
+
let historyAction: HistoryAction | undefined;
|
|
210
|
+
const historyAttr = el.getAttribute('data-swup-history');
|
|
211
|
+
if (historyAttr && ['push', 'replace'].includes(historyAttr)) {
|
|
212
|
+
historyAction = historyAttr as HistoryAction;
|
|
213
|
+
}
|
|
243
214
|
|
|
244
215
|
// Exit early if the link should be ignored
|
|
245
|
-
if (this.shouldIgnoreVisit(href, { el
|
|
216
|
+
if (this.shouldIgnoreVisit(href, { el, event })) {
|
|
246
217
|
return;
|
|
247
218
|
}
|
|
248
219
|
|
|
220
|
+
this.context = this.createContext({
|
|
221
|
+
to: url,
|
|
222
|
+
hash,
|
|
223
|
+
transition,
|
|
224
|
+
el,
|
|
225
|
+
event,
|
|
226
|
+
action: historyAction
|
|
227
|
+
});
|
|
228
|
+
|
|
249
229
|
// Exit early if control key pressed
|
|
250
230
|
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
251
|
-
this.
|
|
231
|
+
this.hooks.trigger('openPageInNewTab', { href });
|
|
252
232
|
return;
|
|
253
233
|
}
|
|
254
234
|
|
|
@@ -257,53 +237,41 @@ export default class Swup {
|
|
|
257
237
|
return;
|
|
258
238
|
}
|
|
259
239
|
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// Handle links to the same page and exit early, where applicable
|
|
264
|
-
if (!url || url === getCurrentUrl()) {
|
|
265
|
-
this.handleLinkToSamePage(url, hash, event);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
240
|
+
this.hooks.triggerSync('clickLink', { el, event }, () => {
|
|
241
|
+
const from = this.context.from?.url ?? '';
|
|
268
242
|
|
|
269
|
-
|
|
270
|
-
if (this.isSameResolvedUrl(url, getCurrentUrl())) return;
|
|
271
|
-
|
|
272
|
-
// Store the element that should be scrolled to after loading the next page
|
|
273
|
-
this.scrollToElement = hash || null;
|
|
274
|
-
|
|
275
|
-
// Get the custom transition name, if present
|
|
276
|
-
const customTransition = linkEl.getAttribute('data-swup-transition') || undefined;
|
|
277
|
-
|
|
278
|
-
// Get the history action, if set
|
|
279
|
-
let history: HistoryAction | undefined;
|
|
280
|
-
const historyAttr = linkEl.getAttribute('data-swup-history');
|
|
281
|
-
if (historyAttr && ['push', 'replace'].includes(historyAttr)) {
|
|
282
|
-
history = historyAttr as HistoryAction;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Finally, proceed with loading the page
|
|
286
|
-
this.performPageLoad({ url, customTransition, history });
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
handleLinkToSamePage(url: string, hash: string, event: DelegateEvent<MouseEvent>) {
|
|
290
|
-
// Emit event and exit early if the url points to the same page without hash
|
|
291
|
-
if (!hash) {
|
|
292
|
-
this.triggerEvent('samePage', event);
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// link to the same URL with hash
|
|
297
|
-
this.triggerEvent('samePageWithHash', event);
|
|
298
|
-
|
|
299
|
-
const element = getAnchorElement(hash);
|
|
300
|
-
|
|
301
|
-
// Warn and exit early if no matching element was found for the hash
|
|
302
|
-
if (!element) {
|
|
303
|
-
return console.warn(`Element for offset not found (#${hash})`);
|
|
304
|
-
}
|
|
243
|
+
event.preventDefault();
|
|
305
244
|
|
|
306
|
-
|
|
245
|
+
// Handle links to the same page: with or without hash
|
|
246
|
+
if (!url || url === from) {
|
|
247
|
+
if (hash) {
|
|
248
|
+
updateHistoryRecord(url + hash);
|
|
249
|
+
this.hooks.triggerSync(
|
|
250
|
+
'samePageWithHash',
|
|
251
|
+
{ hash, options: { behavior: 'auto' } },
|
|
252
|
+
(context, { hash, options }) => {
|
|
253
|
+
const target = this.getAnchorElement(hash);
|
|
254
|
+
if (target) {
|
|
255
|
+
target.scrollIntoView(options);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
} else {
|
|
260
|
+
this.hooks.triggerSync('samePage', undefined, () => {
|
|
261
|
+
window.scroll({ top: 0, left: 0, behavior: 'auto' });
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Exit early if the resolved path hasn't changed
|
|
268
|
+
if (this.isSameResolvedUrl(url, from)) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Finally, proceed with loading the page
|
|
273
|
+
this.performPageLoad(url, { transition, history: historyAction });
|
|
274
|
+
});
|
|
307
275
|
}
|
|
308
276
|
|
|
309
277
|
triggerWillOpenNewWindow(triggerEl: Element) {
|
|
@@ -314,6 +282,8 @@ export default class Swup {
|
|
|
314
282
|
}
|
|
315
283
|
|
|
316
284
|
popStateHandler(event: PopStateEvent) {
|
|
285
|
+
const href = event.state?.url ?? location.href;
|
|
286
|
+
|
|
317
287
|
// Exit early if this event should be ignored
|
|
318
288
|
if (this.options.skipPopStateHandling(event)) {
|
|
319
289
|
return;
|
|
@@ -324,29 +294,31 @@ export default class Swup {
|
|
|
324
294
|
return;
|
|
325
295
|
}
|
|
326
296
|
|
|
327
|
-
const href = event.state?.url ?? location.href;
|
|
328
|
-
|
|
329
297
|
// Exit early if the link should be ignored
|
|
330
298
|
if (this.shouldIgnoreVisit(href, { event })) {
|
|
331
299
|
return;
|
|
332
300
|
}
|
|
333
301
|
|
|
334
302
|
const { url, hash } = Location.fromUrl(href);
|
|
303
|
+
const animate = this.options.animateHistoryBrowsing;
|
|
304
|
+
const resetScroll = this.options.animateHistoryBrowsing;
|
|
305
|
+
this.context = this.createContext({
|
|
306
|
+
to: url,
|
|
307
|
+
hash,
|
|
308
|
+
event,
|
|
309
|
+
animate,
|
|
310
|
+
resetScroll,
|
|
311
|
+
popstate: true
|
|
312
|
+
});
|
|
335
313
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
this.triggerEvent('popState', event);
|
|
343
|
-
|
|
344
|
-
if (!this.options.animateHistoryBrowsing) {
|
|
345
|
-
document.documentElement.classList.remove('is-animating');
|
|
346
|
-
cleanupAnimationClasses();
|
|
347
|
-
}
|
|
314
|
+
// Does this even do anything?
|
|
315
|
+
// if (!hash) {
|
|
316
|
+
// event.preventDefault();
|
|
317
|
+
// }
|
|
348
318
|
|
|
349
|
-
this.
|
|
319
|
+
this.hooks.triggerSync('popState', { event }, () => {
|
|
320
|
+
this.performPageLoad(url);
|
|
321
|
+
});
|
|
350
322
|
}
|
|
351
323
|
|
|
352
324
|
/**
|
|
@@ -3,6 +3,7 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
|
|
4
4
|
import pckg from '../../package.json';
|
|
5
5
|
import Swup, { Options, Plugin } from '../index.js';
|
|
6
|
+
import * as SwupTS from '../Swup.js';
|
|
6
7
|
|
|
7
8
|
const baseUrl = window.location.origin;
|
|
8
9
|
|
|
@@ -51,6 +52,10 @@ describe('Exports', () => {
|
|
|
51
52
|
expect(swup.version).not.toBeUndefined();
|
|
52
53
|
expect(swup.version).toEqual(pckg.version);
|
|
53
54
|
});
|
|
55
|
+
|
|
56
|
+
it('UMD compatibility: Swup.ts should only have a default export', () => {
|
|
57
|
+
expect(Object.keys(SwupTS)).toEqual(['default']);
|
|
58
|
+
});
|
|
54
59
|
});
|
|
55
60
|
|
|
56
61
|
describe('ignoreVisit', () => {
|
|
@@ -82,7 +87,7 @@ describe('ignoreVisit', () => {
|
|
|
82
87
|
it('should be called from loadPage method', () => {
|
|
83
88
|
const ignoreVisit = vi.fn(() => true);
|
|
84
89
|
const swup = new Swup({ ignoreVisit });
|
|
85
|
-
swup.loadPage(
|
|
90
|
+
swup.loadPage('/path/');
|
|
86
91
|
|
|
87
92
|
expect(ignoreVisit.mock.calls).toHaveLength(1);
|
|
88
93
|
});
|
package/src/helpers/Location.ts
CHANGED
|
@@ -5,30 +5,33 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export class Location extends URL {
|
|
8
|
-
constructor(url: string, base: string = document.baseURI) {
|
|
8
|
+
constructor(url: URL | string, base: string = document.baseURI) {
|
|
9
9
|
super(url.toString(), base);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* The full local path including query params.
|
|
14
|
+
*/
|
|
15
|
+
get url(): string {
|
|
13
16
|
return this.pathname + this.search;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Instantiate a Location from an element's href attribute
|
|
18
|
-
* @param
|
|
21
|
+
* @param el
|
|
19
22
|
* @return new Location instance
|
|
20
23
|
*/
|
|
21
|
-
static fromElement(el:
|
|
22
|
-
const href = el.getAttribute('href') || el.getAttribute('xlink:href');
|
|
24
|
+
static fromElement(el: Element): Location {
|
|
25
|
+
const href = el.getAttribute('href') || el.getAttribute('xlink:href') || '';
|
|
23
26
|
return new Location(href!);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* Instantiate a Location from a URL object or string
|
|
28
|
-
* @param
|
|
31
|
+
* @param url
|
|
29
32
|
* @return new Location instance
|
|
30
33
|
*/
|
|
31
|
-
static fromUrl(url: string): Location {
|
|
34
|
+
static fromUrl(url: URL | string): Location {
|
|
32
35
|
return new Location(url);
|
|
33
36
|
}
|
|
34
37
|
}
|