vike 0.4.180 → 0.4.181
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/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +3 -0
- package/dist/cjs/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +1 -2
- package/dist/cjs/{shared/route → node/runtime/renderPage}/resolveRedirects.js +9 -11
- package/dist/cjs/node/runtime/renderPage.js +6 -9
- package/dist/cjs/shared/getPageContextUrlComputed.js +43 -37
- package/dist/cjs/shared/modifyUrl.js +31 -0
- package/dist/cjs/shared/route/abort.js +4 -10
- package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +3 -1
- package/dist/cjs/utils/parseUrl.js +168 -87
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/cjs/utils/redirectHard.js +7 -0
- package/dist/cjs/utils/urlToFile.js +1 -1
- package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +1 -1
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +2 -2
- package/dist/esm/client/client-routing-runtime/navigate.js +2 -1
- package/dist/esm/client/client-routing-runtime/prefetch.js +5 -4
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +7 -7
- package/dist/esm/client/client-routing-runtime/skipLink.js +11 -22
- package/dist/esm/client/client-routing-runtime/utils.d.ts +1 -2
- package/dist/esm/client/client-routing-runtime/utils.js +1 -2
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +3 -0
- package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +2 -3
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +5 -5
- package/dist/esm/{shared/route → node/runtime/renderPage}/resolveRedirects.js +9 -11
- package/dist/esm/node/runtime/renderPage.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage.js +7 -10
- package/dist/esm/shared/getPageContextUrlComputed.d.ts +2 -24
- package/dist/esm/shared/getPageContextUrlComputed.js +43 -37
- package/dist/esm/shared/modifyUrl.d.ts +14 -0
- package/dist/esm/shared/modifyUrl.js +28 -0
- package/dist/esm/shared/route/abort.js +5 -11
- package/dist/esm/shared/route/executeOnBeforeRouteHook.js +4 -2
- package/dist/esm/types/index.d.ts +1 -1
- package/dist/esm/utils/parseUrl.d.ts +43 -10
- package/dist/esm/utils/parseUrl.js +167 -86
- package/dist/esm/utils/projectInfo.d.ts +2 -2
- package/dist/esm/utils/projectInfo.js +1 -1
- package/dist/esm/utils/redirectHard.d.ts +1 -0
- package/dist/esm/utils/redirectHard.js +3 -0
- package/dist/esm/utils/urlToFile.js +1 -1
- package/package.json +17 -2
- package/dist/cjs/utils/isExternalLink.js +0 -7
- package/dist/cjs/utils/serverSideRouteTo.js +0 -7
- package/dist/esm/utils/isExternalLink.d.ts +0 -2
- package/dist/esm/utils/isExternalLink.js +0 -4
- package/dist/esm/utils/serverSideRouteTo.d.ts +0 -2
- package/dist/esm/utils/serverSideRouteTo.js +0 -4
- /package/dist/esm/{shared/route → node/runtime/renderPage}/resolveRedirects.d.ts +0 -0
|
@@ -6,35 +6,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
7
|
};
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
9
|
+
exports.createUrlFromComponents = exports.assertUrlComponents = exports.isBaseServer = exports.isUrlExternal = exports.isUrlRedirectTarget = exports.isUri = exports.isUrl = exports.assertUsageUrlRedirectTarget = exports.assertUsageUrlPathnameAbsolute = exports.assertUsageUrlPathname = exports.parseUrl = void 0;
|
|
10
10
|
const slice_js_1 = require("./slice.js");
|
|
11
11
|
const assert_js_1 = require("./assert.js");
|
|
12
12
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
13
|
-
function isParsable(url) {
|
|
14
|
-
// `parseUrl()` works with these URLs
|
|
15
|
-
return (isUrlWithProtocol(url) ||
|
|
16
|
-
url.startsWith('/') ||
|
|
17
|
-
url.startsWith('.') ||
|
|
18
|
-
url.startsWith('?') ||
|
|
19
|
-
url.startsWith('#') ||
|
|
20
|
-
url === '');
|
|
21
|
-
}
|
|
22
|
-
exports.isParsable = isParsable;
|
|
23
|
-
function assertUsageUrl(url, errPrefix) {
|
|
24
|
-
(0, assert_js_1.assert)(errPrefix.includes(' but '));
|
|
25
|
-
(0, assert_js_1.assertUsage)(typeof url === 'string', `${errPrefix} should be a string`);
|
|
26
|
-
if (isParsable(url))
|
|
27
|
-
return;
|
|
28
|
-
if (!url.startsWith('/') && !url.includes(':')) {
|
|
29
|
-
(0, assert_js_1.assertUsage)(false, `${errPrefix} is ${picocolors_1.default.cyan(url)} and it should be /${picocolors_1.default.cyan(url)} instead (URL pathnames should start with a leading slash)`);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
(0, assert_js_1.assertUsage)(false, `${errPrefix} isn't a valid URL`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
exports.assertUsageUrl = assertUsageUrl;
|
|
36
13
|
function parseUrl(url, baseServer) {
|
|
37
|
-
(0, assert_js_1.assert)(
|
|
14
|
+
(0, assert_js_1.assert)(isUrl(url), url);
|
|
38
15
|
(0, assert_js_1.assert)(baseServer.startsWith('/'));
|
|
39
16
|
// Hash
|
|
40
17
|
const [urlWithoutHash, ...hashList] = url.split('#');
|
|
@@ -54,18 +31,24 @@ function parseUrl(url, baseServer) {
|
|
|
54
31
|
searchAll[key] = [...(searchAll.hasOwnProperty(key) ? searchAll[key] : []), val];
|
|
55
32
|
});
|
|
56
33
|
// Origin + pathname
|
|
57
|
-
|
|
58
|
-
(0, assert_js_1.assert)(origin === null || origin === decodeSafe(origin)); // AFAICT decoding the origin is useless
|
|
59
|
-
(0, assert_js_1.assert)(pathnameResolved.startsWith('/'));
|
|
60
|
-
(0, assert_js_1.assert)(origin === null || url.startsWith(origin));
|
|
61
|
-
// `pathnameOriginal`
|
|
34
|
+
let { protocol, origin, pathnameAbsoluteWithBase } = getPathnameAbsoluteWithBase(urlWithoutHashNorSearch, baseServer);
|
|
62
35
|
const pathnameOriginal = urlWithoutHashNorSearch.slice((origin || '').length);
|
|
63
36
|
assertUrlComponents(url, origin, pathnameOriginal, searchOriginal, hashOriginal);
|
|
64
37
|
// Base URL
|
|
65
|
-
let { pathname, hasBaseServer } =
|
|
38
|
+
let { pathname, hasBaseServer } = removeBaseServer(pathnameAbsoluteWithBase, baseServer);
|
|
39
|
+
// pageContext.urlParsed.href
|
|
40
|
+
const href = createUrlFromComponents(origin, pathname, searchOriginal, hashOriginal);
|
|
41
|
+
// pageContext.urlParsed.{hostname, port}
|
|
42
|
+
const host = !origin ? null : origin.slice(protocol.length);
|
|
43
|
+
const { hostname, port } = parseHost(host, url);
|
|
44
|
+
// decode after setting href
|
|
66
45
|
pathname = decodePathname(pathname);
|
|
67
46
|
(0, assert_js_1.assert)(pathname.startsWith('/'));
|
|
68
47
|
return {
|
|
48
|
+
href,
|
|
49
|
+
protocol,
|
|
50
|
+
hostname,
|
|
51
|
+
port,
|
|
69
52
|
origin,
|
|
70
53
|
pathname,
|
|
71
54
|
pathnameOriginal: pathnameOriginal,
|
|
@@ -97,20 +80,20 @@ function decodePathname(urlPathname) {
|
|
|
97
80
|
.join('/');
|
|
98
81
|
return urlPathname;
|
|
99
82
|
}
|
|
100
|
-
function
|
|
83
|
+
function getPathnameAbsoluteWithBase(url, baseServer) {
|
|
101
84
|
// Search and hash already extracted
|
|
102
85
|
(0, assert_js_1.assert)(!url.includes('?') && !url.includes('#'));
|
|
103
86
|
// url has origin
|
|
104
87
|
{
|
|
105
|
-
const { origin, pathname } = parseOrigin(url);
|
|
88
|
+
const { protocol, origin, pathname } = parseOrigin(url);
|
|
106
89
|
if (origin) {
|
|
107
|
-
return { origin, pathname };
|
|
90
|
+
return { protocol, origin, pathnameAbsoluteWithBase: pathname };
|
|
108
91
|
}
|
|
109
92
|
(0, assert_js_1.assert)(pathname === url);
|
|
110
93
|
}
|
|
111
94
|
// url doesn't have origin
|
|
112
95
|
if (url.startsWith('/')) {
|
|
113
|
-
return { origin: null,
|
|
96
|
+
return { protocol: null, origin: null, pathnameAbsoluteWithBase: url };
|
|
114
97
|
}
|
|
115
98
|
else {
|
|
116
99
|
// url is a relative path
|
|
@@ -125,21 +108,70 @@ function getPathname(url, baseServer) {
|
|
|
125
108
|
else {
|
|
126
109
|
base = baseServer;
|
|
127
110
|
}
|
|
128
|
-
const
|
|
129
|
-
return { origin: null,
|
|
111
|
+
const pathnameAbsoluteWithBase = resolveUrlPathnameRelative(url, base);
|
|
112
|
+
return { protocol: null, origin: null, pathnameAbsoluteWithBase: pathnameAbsoluteWithBase };
|
|
130
113
|
}
|
|
131
114
|
}
|
|
132
115
|
function parseOrigin(url) {
|
|
133
116
|
if (!isUrlWithProtocol(url)) {
|
|
134
|
-
|
|
135
|
-
return { pathname: url, origin: null };
|
|
117
|
+
return { pathname: url, origin: null, protocol: null };
|
|
136
118
|
}
|
|
137
119
|
else {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
120
|
+
const { protocol, uriWithoutProtocol } = parseProtocol(url);
|
|
121
|
+
(0, assert_js_1.assert)(protocol);
|
|
122
|
+
const [host, ...rest] = uriWithoutProtocol.split('/');
|
|
123
|
+
const origin = protocol + host;
|
|
124
|
+
const pathname = '/' + rest.join('/');
|
|
125
|
+
return { pathname, origin, protocol };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function parseHost(host, url) {
|
|
129
|
+
const ret = { hostname: null, port: null };
|
|
130
|
+
if (!host)
|
|
131
|
+
return ret;
|
|
132
|
+
// hostname
|
|
133
|
+
const [hostname, ...rest] = host.split(':');
|
|
134
|
+
ret.hostname = hostname;
|
|
135
|
+
// port
|
|
136
|
+
if (rest.length > 0) {
|
|
137
|
+
(0, assert_js_1.assert)(rest.length === 1, url);
|
|
138
|
+
const portStr = rest[0];
|
|
139
|
+
const port = parseInt(portStr, 10);
|
|
140
|
+
(0, assert_js_1.assert)(port || port === 0, url);
|
|
141
|
+
ret.port = port;
|
|
142
142
|
}
|
|
143
|
+
return ret;
|
|
144
|
+
}
|
|
145
|
+
function parseProtocol(uri) {
|
|
146
|
+
const SEP = ':';
|
|
147
|
+
const [before, ...after] = uri.split(SEP);
|
|
148
|
+
if (after.length === 0 ||
|
|
149
|
+
// https://github.com/vikejs/vike/commit/886a99ff21e86a8ca699a25cee7edc184aa058e4#r143308934
|
|
150
|
+
// https://en.wikipedia.org/wiki/List_of_URI_schemes
|
|
151
|
+
// https://www.rfc-editor.org/rfc/rfc7595
|
|
152
|
+
!/^[a-z][a-z0-9\+\-]*$/i.test(before)) {
|
|
153
|
+
return { protocol: null, uriWithoutProtocol: uri };
|
|
154
|
+
}
|
|
155
|
+
let protocol = before + SEP;
|
|
156
|
+
let uriWithoutProtocol = after.join(SEP);
|
|
157
|
+
const SEP2 = '//';
|
|
158
|
+
if (uriWithoutProtocol.startsWith(SEP2)) {
|
|
159
|
+
protocol = protocol + SEP2;
|
|
160
|
+
uriWithoutProtocol = uriWithoutProtocol.slice(SEP2.length);
|
|
161
|
+
}
|
|
162
|
+
return { protocol, uriWithoutProtocol };
|
|
163
|
+
}
|
|
164
|
+
function isUrlProtocol(protocol) {
|
|
165
|
+
// Is there an altenrative to having a blacklist?
|
|
166
|
+
// - If the blacklist becomes too big, maybe use a whitelist instead ['tauri://', 'file://', 'capacitor://', 'http://', 'https://']
|
|
167
|
+
const blacklist = [
|
|
168
|
+
// https://docs.ipfs.tech/how-to/address-ipfs-on-web
|
|
169
|
+
'ipfs://',
|
|
170
|
+
'ipns://'
|
|
171
|
+
];
|
|
172
|
+
if (blacklist.includes(protocol))
|
|
173
|
+
return false;
|
|
174
|
+
return protocol.endsWith('://');
|
|
143
175
|
}
|
|
144
176
|
// Adapted from https://stackoverflow.com/questions/14780350/convert-relative-path-to-absolute-using-javascript/14780463#14780463
|
|
145
177
|
function resolveUrlPathnameRelative(pathnameRelative, base) {
|
|
@@ -170,34 +202,15 @@ function resolveUrlPathnameRelative(pathnameRelative, base) {
|
|
|
170
202
|
pathnameAbsolute = '/' + pathnameAbsolute;
|
|
171
203
|
return pathnameAbsolute;
|
|
172
204
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
assertUsage(
|
|
176
|
-
!baseServer.startsWith('http'),
|
|
177
|
-
usageErrorMessagePrefix +
|
|
178
|
-
'`base` is not allowed to start with `http`. Consider using `baseAssets` instead, see https://vike.dev/base-url'
|
|
179
|
-
)
|
|
180
|
-
assertUsage(
|
|
181
|
-
baseServer.startsWith('/'),
|
|
182
|
-
usageErrorMessagePrefix + 'Wrong `base` value `' + baseServer + '`; `base` should start with `/`.'
|
|
183
|
-
)
|
|
184
|
-
assert(isBaseServer(baseServer))
|
|
185
|
-
}
|
|
186
|
-
*/
|
|
187
|
-
function assertPathname(urlPathname) {
|
|
188
|
-
(0, assert_js_1.assert)(urlPathname.startsWith('/'));
|
|
189
|
-
(0, assert_js_1.assert)(!urlPathname.includes('?'));
|
|
190
|
-
(0, assert_js_1.assert)(!urlPathname.includes('#'));
|
|
191
|
-
}
|
|
192
|
-
function analyzeBaseServer(urlPathnameWithBase, baseServer) {
|
|
193
|
-
assertPathname(urlPathnameWithBase);
|
|
205
|
+
function removeBaseServer(pathnameAbsoluteWithBase, baseServer) {
|
|
206
|
+
(0, assert_js_1.assert)(pathnameAbsoluteWithBase.startsWith('/'));
|
|
194
207
|
(0, assert_js_1.assert)(isBaseServer(baseServer));
|
|
195
208
|
// Mutable
|
|
196
|
-
let urlPathname =
|
|
209
|
+
let urlPathname = pathnameAbsoluteWithBase;
|
|
197
210
|
(0, assert_js_1.assert)(urlPathname.startsWith('/'));
|
|
198
211
|
(0, assert_js_1.assert)(baseServer.startsWith('/'));
|
|
199
212
|
if (baseServer === '/') {
|
|
200
|
-
const pathname =
|
|
213
|
+
const pathname = pathnameAbsoluteWithBase;
|
|
201
214
|
return { pathname, hasBaseServer: true };
|
|
202
215
|
}
|
|
203
216
|
// Support `url === '/some-base-url' && baseServer === '/some-base-url/'`
|
|
@@ -207,7 +220,7 @@ function analyzeBaseServer(urlPathnameWithBase, baseServer) {
|
|
|
207
220
|
(0, assert_js_1.assert)(urlPathname === baseServerNormalized);
|
|
208
221
|
}
|
|
209
222
|
if (!urlPathname.startsWith(baseServerNormalized)) {
|
|
210
|
-
const pathname =
|
|
223
|
+
const pathname = pathnameAbsoluteWithBase;
|
|
211
224
|
return { pathname, hasBaseServer: false };
|
|
212
225
|
}
|
|
213
226
|
(0, assert_js_1.assert)(urlPathname.startsWith('/') || urlPathname.startsWith('http'));
|
|
@@ -222,30 +235,98 @@ function isBaseServer(baseServer) {
|
|
|
222
235
|
return baseServer.startsWith('/');
|
|
223
236
|
}
|
|
224
237
|
exports.isBaseServer = isBaseServer;
|
|
225
|
-
function assertUrlComponents(url, origin,
|
|
226
|
-
const urlRecreated = createUrlFromComponents(origin,
|
|
238
|
+
function assertUrlComponents(url, origin, pathnameOriginal, searchOriginal, hashOriginal) {
|
|
239
|
+
const urlRecreated = createUrlFromComponents(origin, pathnameOriginal, searchOriginal, hashOriginal);
|
|
227
240
|
(0, assert_js_1.assert)(url === urlRecreated);
|
|
228
241
|
}
|
|
229
242
|
exports.assertUrlComponents = assertUrlComponents;
|
|
230
|
-
function createUrlFromComponents(origin, pathname,
|
|
231
|
-
const urlRecreated = `${origin || ''}${pathname}${
|
|
243
|
+
function createUrlFromComponents(origin, pathname, search, hash) {
|
|
244
|
+
const urlRecreated = `${origin || ''}${pathname}${search || ''}${hash || ''}`;
|
|
232
245
|
return urlRecreated;
|
|
233
246
|
}
|
|
234
247
|
exports.createUrlFromComponents = createUrlFromComponents;
|
|
235
|
-
function
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
248
|
+
function isUrl(url) {
|
|
249
|
+
// parseUrl() works with these URLs
|
|
250
|
+
return isUrlWithProtocol(url) || url.startsWith('/') || isUrlPathnameRelative(url);
|
|
251
|
+
}
|
|
252
|
+
exports.isUrl = isUrl;
|
|
253
|
+
function isUrlRedirectTarget(url) {
|
|
254
|
+
return url.startsWith('/') || isUri(url) || isUrlWithProtocol(url);
|
|
255
|
+
}
|
|
256
|
+
exports.isUrlRedirectTarget = isUrlRedirectTarget;
|
|
257
|
+
function isUrlPathnameRelative(url) {
|
|
258
|
+
return ['.', '?', '#'].some((c) => url.startsWith(c)) || url === '';
|
|
259
|
+
}
|
|
260
|
+
function isUrlExternal(url) {
|
|
261
|
+
return !url.startsWith('/') && !isUrlPathnameRelative(url);
|
|
262
|
+
}
|
|
263
|
+
exports.isUrlExternal = isUrlExternal;
|
|
264
|
+
/*
|
|
265
|
+
URL with protocol.
|
|
266
|
+
|
|
267
|
+
http://example.com
|
|
268
|
+
https://exmaple.com
|
|
269
|
+
tauri://localhost
|
|
270
|
+
file://example.com
|
|
271
|
+
capacitor://localhost/assets/chunks/chunk-DJBYDrsP.js
|
|
272
|
+
|
|
273
|
+
[Tauri](https://github.com/vikejs/vike/issues/808)
|
|
274
|
+
[Electron (`file://`)](https://github.com/vikejs/vike/issues/1557)
|
|
275
|
+
[Capacitor](https://github.com/vikejs/vike/issues/1706)
|
|
276
|
+
*/
|
|
277
|
+
function isUrlWithProtocol(url) {
|
|
278
|
+
const { protocol } = parseProtocol(url);
|
|
279
|
+
return !!protocol && isUrlProtocol(protocol);
|
|
280
|
+
}
|
|
281
|
+
/*
|
|
282
|
+
URIs that aren't URLs.
|
|
283
|
+
|
|
284
|
+
mailto:john@example.com
|
|
285
|
+
|
|
286
|
+
ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/wiki/Vincent_van_Gogh.html
|
|
287
|
+
|
|
288
|
+
magnet:?xt=urn:btih:3a15e1ac49683d91b20c2ffc252ea612a6c01bd7&dn=The.Empire.Strikes.Back.1980.Remastered.1080p.BluRay.DDP.7.1.x265-EDGE2020.mkv&xl=3225443573&tr=udp://tracker.opentrackr.org:1337/announce&tr=udp://tracker.torrent.eu.org:451&tr=udp://open.stealth.si:80/announce&tr=udp://tracker.openbittorrent.com:6969&tr=udp://tracker.tiny-vps.com:6969/announce&tr=udp://open.demonii.com:1337
|
|
289
|
+
|
|
290
|
+
We need to treat URIs differently than URLs.
|
|
291
|
+
- For example, we cannot parse URIs (their structure is unknown e.g. a `magnet:` URI is completely different than a `http://` URL).
|
|
292
|
+
- The protocols tauri:// file:// capacitor:// follow the same structure as http:// and https:// URLs.
|
|
293
|
+
- Thus we can parse them like http:// and https:// URLs.
|
|
294
|
+
*/
|
|
295
|
+
function isUri(uri) {
|
|
296
|
+
const { protocol } = parseProtocol(uri);
|
|
297
|
+
return !!protocol && !isUrlProtocol(uri);
|
|
298
|
+
}
|
|
299
|
+
exports.isUri = isUri;
|
|
300
|
+
function assertUsageUrlPathname(url, errPrefix) {
|
|
301
|
+
assertUsageUrl(url, errPrefix, { allowRelative: true });
|
|
302
|
+
}
|
|
303
|
+
exports.assertUsageUrlPathname = assertUsageUrlPathname;
|
|
304
|
+
function assertUsageUrlPathnameAbsolute(url, errPrefix) {
|
|
305
|
+
assertUsageUrl(url, errPrefix);
|
|
306
|
+
}
|
|
307
|
+
exports.assertUsageUrlPathnameAbsolute = assertUsageUrlPathnameAbsolute;
|
|
308
|
+
function assertUsageUrlRedirectTarget(url, errPrefix, isUnresolved) {
|
|
309
|
+
assertUsageUrl(url, errPrefix, { isRedirectTarget: isUnresolved ? 'unresolved' : true });
|
|
310
|
+
}
|
|
311
|
+
exports.assertUsageUrlRedirectTarget = assertUsageUrlRedirectTarget;
|
|
312
|
+
function assertUsageUrl(url, errPrefix, { allowRelative, isRedirectTarget } = {}) {
|
|
313
|
+
if (url.startsWith('/'))
|
|
314
|
+
return;
|
|
315
|
+
let errMsg = `${errPrefix} is ${picocolors_1.default.string(url)} but it should start with ${picocolors_1.default.string('/')}`;
|
|
316
|
+
if (isRedirectTarget) {
|
|
317
|
+
if (isUrlRedirectTarget(url))
|
|
318
|
+
return;
|
|
319
|
+
errMsg += ` or a protocol (${picocolors_1.default.string('http://')}, ${picocolors_1.default.string('mailto:')}, ...)`;
|
|
320
|
+
if (isRedirectTarget === 'unresolved') {
|
|
321
|
+
if (url === '*')
|
|
322
|
+
return;
|
|
323
|
+
errMsg += `, or be ${picocolors_1.default.string('*')}`;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (allowRelative) {
|
|
327
|
+
if (isUrlPathnameRelative(url))
|
|
328
|
+
return;
|
|
329
|
+
errMsg += ', or be a relative URL';
|
|
330
|
+
}
|
|
331
|
+
(0, assert_js_1.assertUsage)(false, errMsg);
|
|
251
332
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PROJECT_VERSION = exports.projectInfo = void 0;
|
|
4
|
-
const PROJECT_VERSION = '0.4.
|
|
4
|
+
const PROJECT_VERSION = '0.4.181';
|
|
5
5
|
exports.PROJECT_VERSION = PROJECT_VERSION;
|
|
6
6
|
const projectInfo = {
|
|
7
7
|
projectName: 'Vike',
|
|
@@ -5,7 +5,7 @@ const assert_js_1 = require("./assert.js");
|
|
|
5
5
|
const parseUrl_js_1 = require("./parseUrl.js");
|
|
6
6
|
const slice_js_1 = require("./slice.js");
|
|
7
7
|
// - When doing a `.pageContext.json` HTTP request, the base URL should be preserved. (The server-side will handle the base URL.)
|
|
8
|
-
// - While
|
|
8
|
+
// - While pre-rendering there is no base URL
|
|
9
9
|
const baseServer = '/';
|
|
10
10
|
exports.baseServer = baseServer;
|
|
11
11
|
function urlToFile(url, fileExtension, doNotCreateExtraDirectory) {
|
|
@@ -13,7 +13,7 @@ declare function createPageContext(urlOriginal: string): Promise<{
|
|
|
13
13
|
_onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
|
|
14
14
|
_isPageContextObject: boolean;
|
|
15
15
|
} & {
|
|
16
|
-
urlParsed: import("
|
|
16
|
+
urlParsed: import("./utils.js").UrlPublic;
|
|
17
17
|
urlPathname: string;
|
|
18
18
|
url: string;
|
|
19
19
|
}>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { getPageContextFromHooks_isHydration };
|
|
2
2
|
export { getPageContextFromHooks_isNotHydration };
|
|
3
3
|
export { getPageContextFromHooks_serialized };
|
|
4
|
-
import { assert, assertUsage, hasProp, objectAssign, getProjectError,
|
|
4
|
+
import { assert, assertUsage, hasProp, objectAssign, getProjectError, redirectHard, executeHook, isObject, getGlobalObject } from './utils.js';
|
|
5
5
|
import { parse } from '@brillout/json-serializer/parse';
|
|
6
6
|
import { getPageContextSerializedInHtml } from '../shared/getPageContextSerializedInHtml.js';
|
|
7
7
|
import { analyzePageServerSide } from '../../shared/getPageFiles/analyzePageServerSide.js';
|
|
@@ -208,7 +208,7 @@ async function fetchPageContextFromServer(pageContext) {
|
|
|
208
208
|
const isCorrect = contentType && contentType.includes(contentTypeCorrect);
|
|
209
209
|
// Static hosts + page doesn't exist
|
|
210
210
|
if (!isCorrect && response.status === 404) {
|
|
211
|
-
|
|
211
|
+
redirectHard(pageContext.urlOriginal);
|
|
212
212
|
return { is404ServerSideRouted: true };
|
|
213
213
|
}
|
|
214
214
|
assertUsage(isCorrect, `Wrong Content-Type for ${pageContextUrl}: it should be ${contentTypeCorrect} but it's ${contentType} instead. Make sure to properly use pageContext.httpResponse.headers, see https://vike.dev/renderPage`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { navigate };
|
|
2
2
|
export { reload };
|
|
3
3
|
import { renderPageClientSide } from './renderPageClientSide.js';
|
|
4
|
-
import { assertClientRouting, getCurrentUrl } from './utils.js';
|
|
4
|
+
import { assertClientRouting, assertUsageUrlPathname, getCurrentUrl } from './utils.js';
|
|
5
5
|
assertClientRouting();
|
|
6
6
|
/** Programmatically navigate to a new page.
|
|
7
7
|
*
|
|
@@ -12,6 +12,7 @@ assertClientRouting();
|
|
|
12
12
|
* @param overwriteLastHistoryEntry - Don't create a new entry in the browser's history, instead let the new URL replace the current URL. (This effectively removes the current URL from the browser history).
|
|
13
13
|
*/
|
|
14
14
|
async function navigate(url, { keepScrollPosition = false, overwriteLastHistoryEntry = false } = {}) {
|
|
15
|
+
assertUsageUrlPathname(url, '[navigate(url)] url');
|
|
15
16
|
const scrollTarget = { preserveScroll: keepScrollPosition };
|
|
16
17
|
await renderPageClientSide({
|
|
17
18
|
scrollTarget,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { prefetch };
|
|
2
2
|
export { addLinkPrefetchHandlers };
|
|
3
|
-
import { assert, assertClientRouting, assertUsage, assertWarning, checkIfClientRouting, getGlobalObject
|
|
3
|
+
import { assert, assertClientRouting, assertUsage, assertUsageUrlPathname, assertWarning, checkIfClientRouting, getGlobalObject } from './utils.js';
|
|
4
4
|
import { isErrorFetchingStaticAssets, loadUserFilesClientSide } from '../shared/loadUserFilesClientSide.js';
|
|
5
5
|
import { skipLink } from './skipLink.js';
|
|
6
6
|
import { getPrefetchSettings } from './prefetch/getPrefetchSettings.js';
|
|
@@ -10,6 +10,7 @@ import { isClientSideRoutable } from './isClientSideRoutable.js';
|
|
|
10
10
|
import { createPageContext } from './createPageContext.js';
|
|
11
11
|
import { route } from '../../shared/route/index.js';
|
|
12
12
|
import { noRouteMatch } from '../../shared/route/noRouteMatch.js';
|
|
13
|
+
import pc from '@brillout/picocolors';
|
|
13
14
|
assertClientRouting();
|
|
14
15
|
const globalObject = getGlobalObject('prefetch.ts', { linkPrefetchHandlerAdded: new WeakMap() });
|
|
15
16
|
async function prefetchAssets(pageId, pageContext) {
|
|
@@ -36,8 +37,8 @@ async function prefetch(url) {
|
|
|
36
37
|
assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
|
|
37
38
|
showStackTrace: true
|
|
38
39
|
});
|
|
39
|
-
const errPrefix =
|
|
40
|
-
|
|
40
|
+
const errPrefix = '[prefetch(url)] url';
|
|
41
|
+
assertUsageUrlPathname(url, errPrefix);
|
|
41
42
|
if (isAlreadyPrefetched(url))
|
|
42
43
|
return;
|
|
43
44
|
markAsAlreadyPrefetched(url);
|
|
@@ -52,7 +53,7 @@ async function prefetch(url) {
|
|
|
52
53
|
}
|
|
53
54
|
const pageId = pageContextFromRoute._pageId;
|
|
54
55
|
if (!pageId) {
|
|
55
|
-
assertWarning(false, `${errPrefix} ${noRouteMatch}`, {
|
|
56
|
+
assertWarning(false, `${errPrefix} ${pc.string(url)} ${noRouteMatch}`, {
|
|
56
57
|
showStackTrace: true,
|
|
57
58
|
onlyOnce: false
|
|
58
59
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { renderPageClientSide };
|
|
2
2
|
export { getRenderCount };
|
|
3
3
|
export { disableClientRouting };
|
|
4
|
-
import { assert, getCurrentUrl, isSameErrorMessage, objectAssign,
|
|
4
|
+
import { assert, getCurrentUrl, isSameErrorMessage, objectAssign, redirectHard, getGlobalObject, executeHook, hasProp, augmentType } from './utils.js';
|
|
5
5
|
import { getPageContextFromHooks_isHydration, getPageContextFromHooks_isNotHydration, getPageContextFromHooks_serialized } from './getPageContextFromHooks.js';
|
|
6
6
|
import { createPageContext } from './createPageContext.js';
|
|
7
7
|
import { addLinkPrefetchHandlers } from './prefetch.js';
|
|
@@ -25,7 +25,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
25
25
|
assert(isClientSideNavigation === !isHydrationRender); // isHydrationRender === (renderNumber === 1)
|
|
26
26
|
assertNoInfiniteAbortLoop(pageContextsFromRewrite.length, redirectCount);
|
|
27
27
|
if (globalObject.clientRoutingIsDisabled) {
|
|
28
|
-
|
|
28
|
+
redirectHard(urlOriginal);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
await renderPageNominal();
|
|
@@ -89,7 +89,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
if (!isClientRoutable) {
|
|
92
|
-
|
|
92
|
+
redirectHard(urlOriginal);
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
assert(hasProp(pageContextFromRoute, '_pageId', 'string')); // Help TS
|
|
@@ -183,7 +183,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
183
183
|
/* When we can't render the error page, we prefer showing a blank page over letting the server-side try because otherwise:
|
|
184
184
|
- We risk running into an infinite loop of reloads which would overload the server.
|
|
185
185
|
- An infinite reloading page is a even worse UX than a blank page.
|
|
186
|
-
|
|
186
|
+
redirectHard(urlOriginal)
|
|
187
187
|
*/
|
|
188
188
|
console.error(err);
|
|
189
189
|
}
|
|
@@ -228,9 +228,9 @@ async function renderPageClientSide(renderArgs) {
|
|
|
228
228
|
// throw redirect('/some-url')
|
|
229
229
|
if (pageContextAbort._urlRedirect) {
|
|
230
230
|
const urlRedirect = pageContextAbort._urlRedirect.url;
|
|
231
|
-
if (urlRedirect.startsWith('
|
|
231
|
+
if (!urlRedirect.startsWith('/')) {
|
|
232
232
|
// External redirection
|
|
233
|
-
|
|
233
|
+
redirectHard(urlRedirect);
|
|
234
234
|
return;
|
|
235
235
|
}
|
|
236
236
|
else {
|
|
@@ -408,7 +408,7 @@ function handleErrorFetchingStaticAssets(err, pageContext, isHydrationRender) {
|
|
|
408
408
|
else {
|
|
409
409
|
disableClientRouting(err, true);
|
|
410
410
|
}
|
|
411
|
-
|
|
411
|
+
redirectHard(pageContext.urlOriginal);
|
|
412
412
|
return true;
|
|
413
413
|
}
|
|
414
414
|
function disableClientRouting(err, log) {
|
|
@@ -1,30 +1,19 @@
|
|
|
1
1
|
export { skipLink };
|
|
2
2
|
import { getBaseServer } from './getBaseServer.js';
|
|
3
|
-
import { assert, parseUrl, isBaseServer,
|
|
3
|
+
import { assert, parseUrl, isBaseServer, isUrl, isUrlExternal } from './utils.js';
|
|
4
4
|
function skipLink(linkTag) {
|
|
5
5
|
const url = linkTag.getAttribute('href');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return true;
|
|
16
|
-
if (!hasBaseServer(url)) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
if (!isParsable(url)) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
// Purposely last because disableAutomaticLinkInterception will be removed in the major release
|
|
23
|
-
if (!isVikeLink(linkTag))
|
|
24
|
-
return true;
|
|
25
|
-
return false;
|
|
6
|
+
return (url === null ||
|
|
7
|
+
!isUrl(url) ||
|
|
8
|
+
url === '' ||
|
|
9
|
+
isUrlExternal(url) ||
|
|
10
|
+
isHashUrl(url) ||
|
|
11
|
+
isNewTabLink(linkTag) ||
|
|
12
|
+
!hasBaseServer(url) ||
|
|
13
|
+
// Purposely last because disableAutomaticLinkInterception will be removed in the next major release
|
|
14
|
+
!isVikeLink(linkTag));
|
|
26
15
|
}
|
|
27
|
-
// TODO/
|
|
16
|
+
// TODO/next-major-release: remove this in favor of synchronously checking whether URL matches the route of a page (possible since Async Route Functions will be deprecated)
|
|
28
17
|
function isVikeLink(linkTag) {
|
|
29
18
|
const disableAutomaticLinkInterception = isDisableAutomaticLinkInterception();
|
|
30
19
|
if (!disableAutomaticLinkInterception) {
|
|
@@ -15,11 +15,10 @@ export * from '../../utils/objectAssign.js';
|
|
|
15
15
|
export * from '../../utils/parseUrl.js';
|
|
16
16
|
export * from '../../utils/projectInfo.js';
|
|
17
17
|
export * from '../../utils/PromiseType.js';
|
|
18
|
-
export * from '../../utils/
|
|
18
|
+
export * from '../../utils/redirectHard.js';
|
|
19
19
|
export * from '../../utils/sleep.js';
|
|
20
20
|
export * from '../../utils/slice.js';
|
|
21
21
|
export * from '../../utils/throttle.js';
|
|
22
22
|
export * from '../../utils/assertRoutingType.js';
|
|
23
23
|
export * from '../../utils/onPageVisibilityChange.js';
|
|
24
|
-
export * from '../../utils/isExternalLink.js';
|
|
25
24
|
export * from '../../utils/augmentType.js';
|
|
@@ -21,11 +21,10 @@ export * from '../../utils/objectAssign.js';
|
|
|
21
21
|
export * from '../../utils/parseUrl.js';
|
|
22
22
|
export * from '../../utils/projectInfo.js';
|
|
23
23
|
export * from '../../utils/PromiseType.js';
|
|
24
|
-
export * from '../../utils/
|
|
24
|
+
export * from '../../utils/redirectHard.js';
|
|
25
25
|
export * from '../../utils/sleep.js';
|
|
26
26
|
export * from '../../utils/slice.js';
|
|
27
27
|
export * from '../../utils/throttle.js';
|
|
28
28
|
export * from '../../utils/assertRoutingType.js';
|
|
29
29
|
export * from '../../utils/onPageVisibilityChange.js';
|
|
30
|
-
export * from '../../utils/isExternalLink.js';
|
|
31
30
|
export * from '../../utils/augmentType.js';
|
package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js
CHANGED
|
@@ -153,6 +153,9 @@ async function fastGlob(userRootDir, outDirRelativeFromUserRootDir) {
|
|
|
153
153
|
cwd: userRootDir,
|
|
154
154
|
dot: false
|
|
155
155
|
});
|
|
156
|
+
// Make build deterministic, in order to get a stable generated hash for dist/client/assets/entries/entry-client-routing.${hash}.js
|
|
157
|
+
// https://github.com/vikejs/vike/pull/1750
|
|
158
|
+
files.sort();
|
|
156
159
|
return files;
|
|
157
160
|
}
|
|
158
161
|
// Same as getIgnoreAsFilterFn() but as glob pattern
|
package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { assertNoInfiniteHttpRedirect };
|
|
2
|
-
import { assert, assertUsage, getGlobalObject
|
|
2
|
+
import { assert, assertUsage, getGlobalObject } from '../../utils.js';
|
|
3
3
|
import pc from '@brillout/picocolors';
|
|
4
4
|
const globalObject = getGlobalObject('assertNoInfiniteHttpRedirect.ts', {
|
|
5
5
|
redirectGraph: {}
|
|
6
6
|
});
|
|
7
7
|
function assertNoInfiniteHttpRedirect(urlRedirectTarget, urlLogical) {
|
|
8
|
-
if (
|
|
8
|
+
if (!urlRedirectTarget.startsWith('/')) {
|
|
9
9
|
// We assume that urlRedirectTarget points to an origin that is external (not the same origin), and we can therefore assume that the app doesn't define an infinite loop (in itself).
|
|
10
10
|
// - There isn't a reliable way to check whether the redirect points to an external origin or the same origin. For same origins, we assume/hope the user to pass the URL without origin.
|
|
11
11
|
// ```js
|
|
@@ -14,7 +14,6 @@ function assertNoInfiniteHttpRedirect(urlRedirectTarget, urlLogical) {
|
|
|
14
14
|
// ```
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
assert(urlRedirectTarget.startsWith('/'));
|
|
18
17
|
assert(urlLogical.startsWith('/'));
|
|
19
18
|
const graph = copy(globalObject.redirectGraph);
|
|
20
19
|
graph[urlRedirectTarget] ?? (graph[urlRedirectTarget] = new Set());
|