+77
-29
src/lib/redirector.ts
+77
-29
src/lib/redirector.ts
···
1
-
import { base } from '$app/paths';
1
+
import { resolve } from '$app/paths';
2
2
3
-
import { isDid, isHandle, isRecordKey, isTid, parseResourceUri } from '@atcute/lexicons/syntax';
3
+
import { isActorIdentifier, isRecordKey, isTid, parseResourceUri } from '@atcute/lexicons/syntax';
4
4
5
5
import {
6
6
BSKY_FEED_LINK_RE,
···
38
38
if ((match = BSKY_PROFILE_LINK_RE.exec(pathname))) {
39
39
const [, actor] = match;
40
40
41
-
if (!isHandle(actor) && !isDid(actor)) {
41
+
if (!isActorIdentifier(actor)) {
42
42
return null;
43
43
}
44
44
45
-
return { type: 'internal', url: `${base}/${match[1]}` };
45
+
return {
46
+
type: 'internal',
47
+
url: resolve('/(app)/(profile)/[actor=didOrHandle]/(timeline)', { actor: match[1] }),
48
+
};
46
49
}
47
50
48
51
if ((match = BSKY_POST_LINK_RE.exec(pathname))) {
49
52
const [, actor, rkey] = match;
50
53
51
-
if (!isHandle(actor) && !isDid(actor)) {
54
+
if (!isActorIdentifier(actor)) {
52
55
return null;
53
56
}
54
57
if (!isTid(rkey)) {
55
58
return null;
56
59
}
57
60
58
-
return { type: 'internal', url: `${base}/${actor}/${rkey}#main` };
61
+
return {
62
+
type: 'internal',
63
+
url: resolve('/(app)/[actor=did]/[rkey=tid]', { actor, rkey }) + `#main`,
64
+
};
59
65
}
60
66
61
67
if ((match = BSKY_FEED_LINK_RE.exec(pathname))) {
62
68
const [, actor, rkey] = match;
63
69
64
-
if (!isHandle(actor) && !isDid(actor)) {
70
+
if (!isActorIdentifier(actor)) {
65
71
return null;
66
72
}
67
73
if (!isRecordKey(rkey)) {
68
74
return null;
69
75
}
70
76
71
-
return { type: 'internal', url: `${base}/${actor}/feeds/${rkey}` };
77
+
return {
78
+
type: 'internal',
79
+
url: resolve('/(app)/[actor=didOrHandle]/feeds/[rkey=rkey]', { actor, rkey }),
80
+
};
72
81
}
73
82
74
83
if ((match = BSKY_LIST_LINK_RE.exec(pathname))) {
75
84
const [, actor, rkey] = match;
76
85
77
-
if (!isHandle(actor) && !isDid(actor)) {
86
+
if (!isActorIdentifier(actor)) {
78
87
return null;
79
88
}
80
89
if (!isRecordKey(rkey)) {
81
90
return null;
82
91
}
83
92
84
-
return { type: 'internal', url: `${base}/${actor}/lists/${rkey}` };
93
+
return {
94
+
type: 'internal',
95
+
url: resolve('/(app)/[actor=didOrHandle]/lists/[rkey=rkey]', { actor, rkey }),
96
+
};
85
97
}
86
98
87
99
if ((match = BSKY_STARTERPACK_LINK_RE.exec(pathname))) {
88
100
const [, _page, actor, rkey] = match;
89
101
90
-
if (!isHandle(actor) && !isDid(actor)) {
102
+
if (!isActorIdentifier(actor)) {
91
103
return null;
92
104
}
93
105
if (!isRecordKey(rkey)) {
94
106
return null;
95
107
}
96
108
97
-
return { type: 'internal', url: `${base}/${actor}/packs/${rkey}` };
109
+
return {
110
+
type: 'internal',
111
+
url: resolve('/(app)/[actor=didOrHandle]/packs/[rkey=rkey]', { actor, rkey }),
112
+
};
98
113
}
99
114
100
115
if ((match = BSKY_SEARCH_LINK_RE.exec(pathname))) {
···
103
118
return null;
104
119
}
105
120
106
-
return { type: 'internal', url: `${base}/search/posts?q=${encodeURIComponent(query)}` };
121
+
return {
122
+
type: 'internal',
123
+
url: resolve('/(app)/search/posts') + `?q=${encodeURIComponent(query)}`,
124
+
};
107
125
}
108
126
109
127
if ((match = BSKY_HASHTAG_LINK_RE.exec(pathname))) {
110
128
const [, tag] = match;
111
129
112
-
return { type: 'internal', url: `${base}/search/posts?q=${encodeURIComponent('#' + tag)}` };
130
+
return {
131
+
type: 'internal',
132
+
url: resolve('/(app)/search/posts') + `?q=${encodeURIComponent('#' + tag)}`,
133
+
};
113
134
}
114
135
115
136
return null;
···
133
154
if ((match = BSKY_GO_SHORTLINK_RE.exec(pathname))) {
134
155
const [, id] = match;
135
156
136
-
return { type: 'internal', url: `${base}/go/${id}` };
157
+
return {
158
+
type: 'internal',
159
+
url: resolve('/go/[shortid]', { shortid: id }),
160
+
};
137
161
}
138
162
}
139
163
···
149
173
let match: RegExpExecArray | null | undefined;
150
174
151
175
if (host === 'blue.mackuba.eu' && pathname === '/skythread/') {
152
-
const author = url.searchParams.get('author');
153
-
const post = url.searchParams.get('post');
176
+
const actor = url.searchParams.get('author');
177
+
const rkey = url.searchParams.get('post');
154
178
155
-
if (author === null || post === null) {
179
+
if (actor === null || rkey === null) {
156
180
return null;
157
181
}
158
182
159
-
if (!isHandle(author) && !isDid(author)) {
183
+
if (!isActorIdentifier(actor)) {
160
184
return null;
161
185
}
162
-
if (!isTid(post)) {
186
+
if (!isTid(rkey)) {
163
187
return null;
164
188
}
165
189
166
-
return { type: 'internal', url: `${base}/${author}/${post}#main` };
190
+
return {
191
+
type: 'internal',
192
+
url: resolve('/(app)/[actor=did]/[rkey=tid]', { actor, rkey }) + `#main`,
193
+
};
167
194
}
168
195
169
196
if (host === 'skywriter.blue') {
170
197
if ((match = SKYWRITER_UNROLL_RE.exec(pathname))) {
171
198
const [, actor, rkey] = match;
172
199
173
-
if (!isHandle(actor) && !isDid(actor)) {
200
+
if (!isActorIdentifier(actor)) {
174
201
return null;
175
202
}
176
203
if (!isTid(rkey)) {
177
204
return null;
178
205
}
179
206
180
-
return { type: 'internal', url: `${base}/${actor}/${rkey}/unroll` };
207
+
return {
208
+
type: 'internal',
209
+
url: resolve('/(app)/[actor=did]/[rkey=tid]/unroll', { actor, rkey }),
210
+
};
181
211
}
182
212
}
183
213
···
215
245
if (uri.rkey) {
216
246
switch (uri.collection) {
217
247
case 'app.bsky.actor.profile': {
218
-
return { type: 'internal', url: `${base}/${uri.repo}` };
248
+
return {
249
+
type: 'internal',
250
+
url: resolve('/(app)/(profile)/[actor=didOrHandle]/(timeline)', { actor: uri.repo }),
251
+
};
219
252
}
220
253
case 'app.bsky.feed.post': {
221
254
if (!isTid(uri.rkey)) {
222
255
return null;
223
256
}
224
257
225
-
return { type: 'internal', url: `${base}/${uri.repo}/${uri.rkey}#main` };
258
+
return {
259
+
type: 'internal',
260
+
url: resolve('/(app)/[actor=did]/[rkey=tid]', { actor: uri.repo, rkey: uri.rkey }) + `#main`,
261
+
};
226
262
}
227
263
case 'app.bsky.feed.generator': {
228
-
return { type: 'internal', url: `${base}/${uri.repo}/feeds/${uri.rkey}` };
264
+
return {
265
+
type: 'internal',
266
+
url: resolve('/(app)/[actor=didOrHandle]/feeds/[rkey=rkey]', { actor: uri.repo, rkey: uri.rkey }),
267
+
};
229
268
}
230
269
case 'app.bsky.graph.list': {
231
-
return { type: 'internal', url: `${base}/${uri.repo}/lists/${uri.rkey}` };
270
+
return {
271
+
type: 'internal',
272
+
url: resolve('/(app)/[actor=didOrHandle]/lists/[rkey=rkey]', { actor: uri.repo, rkey: uri.rkey }),
273
+
};
232
274
}
233
275
case 'app.bsky.graph.starterpack': {
234
-
return { type: 'internal', url: `${base}/${uri.repo}/packs/${uri.rkey}` };
276
+
return {
277
+
type: 'internal',
278
+
url: resolve('/(app)/[actor=didOrHandle]/packs/[rkey=rkey]', { actor: uri.repo, rkey: uri.rkey }),
279
+
};
235
280
}
236
281
}
237
282
}
238
283
239
284
if (uri.collection === undefined) {
240
-
return { type: 'internal', url: `${base}/${uri.repo}` };
285
+
return {
286
+
type: 'internal',
287
+
url: resolve('/(app)/(profile)/[actor=didOrHandle]/(timeline)', { actor: uri.repo }),
288
+
};
241
289
}
242
290
243
291
return null;