@inlang/paraglide-js 1.7.2 → 1.7.3
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/adapter-utils/index.d.ts +1 -1
- package/dist/adapter-utils/index.js +123 -40
- package/dist/adapter-utils/routing/routeDefinitions.d.ts +14 -4
- package/dist/adapter-utils/routing/sortRoutes.d.ts +1 -0
- package/dist/cli/index.js +2 -2
- package/dist/index.js +2384 -2328
- package/package.json +7 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { negotiateLanguagePreferences } from './negotiation/language.js';
|
|
2
2
|
export { detectLanguageFromPath } from './routing/detectLanguage.js';
|
|
3
|
-
export { bestMatch, resolveRoute, parseRouteDefinition,
|
|
3
|
+
export { bestMatch, resolveRoute, parseRouteDefinition, type PathDefinitionTranslations, type ParamMatcher, type RouteParam, } from './routing/routeDefinitions.js';
|
|
4
4
|
export { validatePathTranslations, prettyPrintPathDefinitionIssues, } from './routing/validatePathTranslations.js';
|
|
5
5
|
export { resolveUserPathDefinitions, type UserPathDefinitionTranslations, } from './routing/resolveUserPathDefinitions.js';
|
|
@@ -109,6 +109,116 @@ function detectLanguageFromPath({
|
|
|
109
109
|
}
|
|
110
110
|
return void 0;
|
|
111
111
|
}
|
|
112
|
+
const EMPTY = { type: "static", content: "", matched: false };
|
|
113
|
+
function sort_routes(routes) {
|
|
114
|
+
const segment_cache = /* @__PURE__ */ new Map();
|
|
115
|
+
function split(id) {
|
|
116
|
+
const parts = [];
|
|
117
|
+
let i = 0;
|
|
118
|
+
while (i <= id.length) {
|
|
119
|
+
const start = id.indexOf("[", i);
|
|
120
|
+
if (start === -1) {
|
|
121
|
+
parts.push({ type: "static", content: id.slice(i), matched: false });
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
parts.push({ type: "static", content: id.slice(i, start), matched: false });
|
|
125
|
+
const type = id[start + 1] === "[" ? "optional" : id[start + 1] === "." ? "rest" : "required";
|
|
126
|
+
const delimiter = type === "optional" ? "]]" : "]";
|
|
127
|
+
const end = id.indexOf(delimiter, start);
|
|
128
|
+
if (end === -1) {
|
|
129
|
+
throw new Error(`Invalid route ID ${id}`);
|
|
130
|
+
}
|
|
131
|
+
const content = id.slice(start, i = end + delimiter.length);
|
|
132
|
+
parts.push({
|
|
133
|
+
type,
|
|
134
|
+
content,
|
|
135
|
+
matched: content.includes("=")
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return parts;
|
|
139
|
+
}
|
|
140
|
+
function get_parts(segment) {
|
|
141
|
+
if (!segment_cache.has(segment)) {
|
|
142
|
+
segment_cache.set(segment, split(segment));
|
|
143
|
+
}
|
|
144
|
+
return segment_cache.get(segment);
|
|
145
|
+
}
|
|
146
|
+
return routes.sort((route_a, route_b) => {
|
|
147
|
+
var _a, _b, _c, _d, _e, _f;
|
|
148
|
+
const segments_a = split_route_id(route_a).map(get_parts);
|
|
149
|
+
const segments_b = split_route_id(route_b).map(get_parts);
|
|
150
|
+
for (let i = 0; i < Math.max(segments_a.length, segments_b.length); i += 1) {
|
|
151
|
+
const segment_a = segments_a[i] ?? [EMPTY];
|
|
152
|
+
const segment_b = segments_b[i] ?? [EMPTY];
|
|
153
|
+
for (let j = 0; j < Math.max(segment_a.length, segment_b.length); j += 1) {
|
|
154
|
+
const a = segment_a[j];
|
|
155
|
+
const b = segment_b[j];
|
|
156
|
+
const dynamic = !!(j % 2);
|
|
157
|
+
if (dynamic) {
|
|
158
|
+
if (!a)
|
|
159
|
+
return -1;
|
|
160
|
+
if (!b)
|
|
161
|
+
return 1;
|
|
162
|
+
const next_a = ((_a = segment_a[j + 1]) == null ? void 0 : _a.content) || ((_c = (_b = segments_a[i + 1]) == null ? void 0 : _b[0]) == null ? void 0 : _c.content);
|
|
163
|
+
const next_b = ((_d = segment_b[j + 1]) == null ? void 0 : _d.content) || ((_f = (_e = segments_b[i + 1]) == null ? void 0 : _e[0]) == null ? void 0 : _f.content);
|
|
164
|
+
if (a.type === "rest" && b.type === "rest") {
|
|
165
|
+
if (next_a && next_b)
|
|
166
|
+
continue;
|
|
167
|
+
if (next_a)
|
|
168
|
+
return -1;
|
|
169
|
+
if (next_b)
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
if (a.type === "rest") {
|
|
173
|
+
return next_a && !next_b ? -1 : 1;
|
|
174
|
+
}
|
|
175
|
+
if (b.type === "rest") {
|
|
176
|
+
return next_b && !next_a ? 1 : -1;
|
|
177
|
+
}
|
|
178
|
+
if (a.matched !== b.matched) {
|
|
179
|
+
return a.matched ? -1 : 1;
|
|
180
|
+
}
|
|
181
|
+
if (a.type !== b.type) {
|
|
182
|
+
if (a.type === "required")
|
|
183
|
+
return -1;
|
|
184
|
+
if (b.type === "required")
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
} else if ((a == null ? void 0 : a.content) !== (b == null ? void 0 : b.content)) {
|
|
188
|
+
if (a === EMPTY)
|
|
189
|
+
return -1;
|
|
190
|
+
if (b === EMPTY)
|
|
191
|
+
return 1;
|
|
192
|
+
return sort_static(a.content, b.content);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return route_a < route_b ? 1 : -1;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function split_route_id(id) {
|
|
200
|
+
return get_route_segments(
|
|
201
|
+
id.replace(/\[\[[^\]]+\]\](?!$)/g, "")
|
|
202
|
+
).filter(Boolean);
|
|
203
|
+
}
|
|
204
|
+
function sort_static(a, b) {
|
|
205
|
+
if (a === b)
|
|
206
|
+
return 0;
|
|
207
|
+
let i = 0;
|
|
208
|
+
while (a[i] || b[i]) {
|
|
209
|
+
const char_a = a[i];
|
|
210
|
+
const char_b = b[i];
|
|
211
|
+
if (char_a !== char_b) {
|
|
212
|
+
if (char_a === void 0)
|
|
213
|
+
return 1;
|
|
214
|
+
if (char_b === void 0)
|
|
215
|
+
return -1;
|
|
216
|
+
return char_a < char_b ? -1 : 1;
|
|
217
|
+
}
|
|
218
|
+
i++;
|
|
219
|
+
}
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
112
222
|
const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
|
|
113
223
|
function parseRouteDefinition(id) {
|
|
114
224
|
const params = [];
|
|
@@ -157,9 +267,7 @@ function parseRouteDefinition(id) {
|
|
|
157
267
|
param_pattern.exec(content)
|
|
158
268
|
);
|
|
159
269
|
if (!match) {
|
|
160
|
-
throw new Error(
|
|
161
|
-
`Invalid param: ${content}. Params and matcher names can only have underscores and alphanumeric characters.`
|
|
162
|
-
);
|
|
270
|
+
throw new Error(`Invalid param: ${content}`);
|
|
163
271
|
}
|
|
164
272
|
const [, is_optional, is_rest, name, matcher] = match;
|
|
165
273
|
params.push({
|
|
@@ -181,7 +289,7 @@ function parseRouteDefinition(id) {
|
|
|
181
289
|
function exec(match, params, matchers) {
|
|
182
290
|
const result = {};
|
|
183
291
|
const values = match.slice(1);
|
|
184
|
-
const values_needing_match = values.filter((
|
|
292
|
+
const values_needing_match = values.filter((v) => v !== void 0);
|
|
185
293
|
let buffered = 0;
|
|
186
294
|
for (const [i, param] of params.entries()) {
|
|
187
295
|
let value = values[i - buffered];
|
|
@@ -225,28 +333,24 @@ function escape(str) {
|
|
|
225
333
|
}
|
|
226
334
|
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
|
|
227
335
|
function resolveRoute(id, params) {
|
|
228
|
-
|
|
229
|
-
return "/" + segments.map(
|
|
336
|
+
return "/" + get_route_segments(id).map(
|
|
230
337
|
(segment) => segment.replace(basic_param_pattern, (_, optional, rest, name) => {
|
|
231
338
|
const param_value = params[name];
|
|
232
339
|
if (!param_value) {
|
|
233
|
-
if (optional)
|
|
234
|
-
return "";
|
|
235
|
-
if (rest && param_value !== void 0)
|
|
340
|
+
if (optional || rest && param_value !== void 0)
|
|
236
341
|
return "";
|
|
237
|
-
|
|
342
|
+
else
|
|
343
|
+
throw new Error(`Missing parameter '${name}' in route ${id}`);
|
|
238
344
|
}
|
|
239
|
-
if (param_value
|
|
240
|
-
throw new Error(
|
|
241
|
-
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
|
|
242
|
-
);
|
|
345
|
+
if (param_value[0] == "/" || param_value.endsWith("/"))
|
|
346
|
+
throw new Error(`Parameter '${name}' in route ${id} cannot start or end with a slash`);
|
|
243
347
|
return param_value;
|
|
244
348
|
})
|
|
245
349
|
).filter(Boolean).join("/");
|
|
246
350
|
}
|
|
247
351
|
function bestMatch(canonicalPath, pathDefinitions, matchers) {
|
|
248
|
-
|
|
249
|
-
for (const pathDefinition of
|
|
352
|
+
const sorted = sort_routes(pathDefinitions);
|
|
353
|
+
for (const pathDefinition of sorted) {
|
|
250
354
|
const route = parseRouteDefinition(pathDefinition);
|
|
251
355
|
const match = route.pattern.exec(removeTrailingSlash(canonicalPath));
|
|
252
356
|
if (!match)
|
|
@@ -254,34 +358,14 @@ function bestMatch(canonicalPath, pathDefinitions, matchers) {
|
|
|
254
358
|
const params = exec(match, route.params, matchers);
|
|
255
359
|
if (!params)
|
|
256
360
|
continue;
|
|
257
|
-
|
|
258
|
-
bestMatch2 = { params, route, id: pathDefinition };
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
const bestMatchNumParams = Object.keys(bestMatch2.route.params).length;
|
|
262
|
-
const currentMatchNumParams = Object.keys(route.params).length;
|
|
263
|
-
if (bestMatchNumParams < currentMatchNumParams) {
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
if (bestMatchNumParams > currentMatchNumParams) {
|
|
267
|
-
bestMatch2 = { params, route, id: pathDefinition };
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
if (bestMatchNumParams === currentMatchNumParams && route.pattern.source.length < bestMatch2.route.pattern.source.length) {
|
|
271
|
-
bestMatch2 = { params, route, id: pathDefinition };
|
|
272
|
-
}
|
|
361
|
+
return { params, id: pathDefinition };
|
|
273
362
|
}
|
|
274
|
-
return
|
|
275
|
-
id: bestMatch2.id,
|
|
276
|
-
params: bestMatch2.params
|
|
277
|
-
} : void 0;
|
|
363
|
+
return void 0;
|
|
278
364
|
}
|
|
279
365
|
function removeTrailingSlash(path) {
|
|
280
366
|
return path.endsWith("/") ? path.slice(0, -1) : path;
|
|
281
367
|
}
|
|
282
|
-
|
|
283
|
-
return route.slice(1).split("/");
|
|
284
|
-
}
|
|
368
|
+
const get_route_segments = (route) => route.slice(1).split("/");
|
|
285
369
|
function validatePathTranslations(pathTranslations, availableLanguageTags, matchers) {
|
|
286
370
|
const issues = [];
|
|
287
371
|
const expectedLanguages = new Set(availableLanguageTags);
|
|
@@ -375,7 +459,6 @@ const fromMessage = (message, availableLanguageTags) => Object.fromEntries(
|
|
|
375
459
|
export {
|
|
376
460
|
bestMatch,
|
|
377
461
|
detectLanguageFromPath,
|
|
378
|
-
exec,
|
|
379
462
|
negotiateLanguagePreferences,
|
|
380
463
|
parseRouteDefinition,
|
|
381
464
|
prettyPrintPathDefinitionIssues,
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export type PathDefinitionTranslations<T extends string = string> = {
|
|
2
2
|
[canonicalPath: `/${string}`]: Record<T, `/${string}`>;
|
|
3
3
|
};
|
|
4
|
+
type Route = {
|
|
5
|
+
params: RouteParam[];
|
|
6
|
+
pattern: RegExp;
|
|
7
|
+
};
|
|
4
8
|
export type RouteParam = {
|
|
5
9
|
name: string;
|
|
6
10
|
matcher: string;
|
|
@@ -12,10 +16,7 @@ export type ParamMatcher = (segment: string) => boolean;
|
|
|
12
16
|
/**
|
|
13
17
|
* Creates the regex pattern, extracts parameter names, and generates types for a route
|
|
14
18
|
*/
|
|
15
|
-
export declare function parseRouteDefinition(id: string):
|
|
16
|
-
params: RouteParam[];
|
|
17
|
-
pattern: RegExp;
|
|
18
|
-
};
|
|
19
|
+
export declare function parseRouteDefinition(id: string): Route;
|
|
19
20
|
export declare function exec(match: RegExpMatchArray, params: RouteParam[], matchers: Record<string, ParamMatcher>): Record<string, string> | undefined;
|
|
20
21
|
/**
|
|
21
22
|
* Populate a route ID with params to resolve a pathname.
|
|
@@ -43,3 +44,12 @@ export declare function bestMatch(canonicalPath: string, pathDefinitions: string
|
|
|
43
44
|
params: Record<string, string>;
|
|
44
45
|
id: string;
|
|
45
46
|
} | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Splits a route id into its segments, removing segments that
|
|
49
|
+
* don't affect the path (i.e. groups). The root route is represented by `/`
|
|
50
|
+
* and will be returned as `['']`.
|
|
51
|
+
* @param {string} route
|
|
52
|
+
* @returns string[]
|
|
53
|
+
*/
|
|
54
|
+
export declare const get_route_segments: (route: string) => string[];
|
|
55
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sort_routes(routes: string[]): string[];
|
package/dist/cli/index.js
CHANGED
|
@@ -32234,7 +32234,7 @@ const addParaglideJsToDevDependencies = async (ctx) => {
|
|
|
32234
32234
|
const ctx1 = await updatePackageJson({
|
|
32235
32235
|
devDependencies: async (devDeps) => ({
|
|
32236
32236
|
...devDeps,
|
|
32237
|
-
"@inlang/paraglide-js": "1.7.
|
|
32237
|
+
"@inlang/paraglide-js": "1.7.3"
|
|
32238
32238
|
})
|
|
32239
32239
|
})(ctx);
|
|
32240
32240
|
ctx.logger.success("Added @inlang/paraglide-js to the devDependencies in package.json.");
|
|
@@ -32321,7 +32321,7 @@ const steps = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
32321
32321
|
runCompiler,
|
|
32322
32322
|
updatePackageJson
|
|
32323
32323
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
32324
|
-
const cli = new Command().name("paraglide-js").addCommand(compileCommand).addCommand(initCommand).showHelpAfterError().version("1.7.
|
|
32324
|
+
const cli = new Command().name("paraglide-js").addCommand(compileCommand).addCommand(initCommand).showHelpAfterError().version("1.7.3");
|
|
32325
32325
|
export {
|
|
32326
32326
|
defaults as Defaults,
|
|
32327
32327
|
steps as Steps,
|