astro 3.5.4 → 3.5.6
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/components/ViewTransitions.astro +16 -8
- package/dist/@types/astro.d.ts +11 -1
- package/dist/cli/add/index.js +9 -1
- package/dist/core/app/index.js +24 -6
- package/dist/core/build/buildPipeline.js +5 -7
- package/dist/core/build/generate.js +83 -73
- package/dist/core/build/internal.d.ts +0 -6
- package/dist/core/build/internal.js +3 -16
- package/dist/core/build/page-data.js +18 -46
- package/dist/core/build/static-build.js +7 -9
- package/dist/core/build/types.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/endpoint/index.d.ts +4 -2
- package/dist/core/endpoint/index.js +22 -4
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/index.js +3 -1
- package/dist/core/pipeline.d.ts +6 -0
- package/dist/core/pipeline.js +17 -8
- package/dist/core/render/context.d.ts +3 -0
- package/dist/core/render/context.js +18 -1
- package/dist/core/render/core.js +3 -1
- package/dist/core/render/result.d.ts +2 -0
- package/dist/core/render/result.js +23 -1
- package/dist/core/routing/manifest/create.js +25 -20
- package/dist/core/routing/manifest/serialization.js +7 -1
- package/dist/core/routing/match.js +4 -1
- package/dist/core/routing/params.js +1 -1
- package/dist/i18n/middleware.d.ts +5 -0
- package/dist/i18n/middleware.js +14 -3
- package/dist/runtime/client/dev-overlay/entrypoint.js +147 -6
- package/dist/runtime/client/dev-overlay/overlay.d.ts +4 -0
- package/dist/runtime/client/dev-overlay/overlay.js +20 -8
- package/dist/runtime/client/dev-overlay/plugins/settings.js +2 -2
- package/dist/runtime/client/dev-overlay/settings.d.ts +2 -2
- package/dist/runtime/client/dev-overlay/settings.js +1 -1
- package/dist/runtime/client/dev-overlay/ui-library/icons.d.ts +1 -0
- package/dist/runtime/client/dev-overlay/ui-library/icons.js +2 -1
- package/dist/runtime/client/dev-overlay/ui-library/toggle.d.ts +2 -0
- package/dist/runtime/client/dev-overlay/ui-library/toggle.js +6 -0
- package/dist/vite-plugin-astro-server/route.js +11 -4
- package/package.json +2 -2
|
@@ -8,16 +8,18 @@ type CreateAPIContext = {
|
|
|
8
8
|
props: Record<string, any>;
|
|
9
9
|
adapterName?: string;
|
|
10
10
|
locales: string[] | undefined;
|
|
11
|
+
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
|
|
12
|
+
defaultLocale: string | undefined;
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
15
|
* Creates a context that holds all the information needed to handle an Astro endpoint.
|
|
14
16
|
*
|
|
15
17
|
* @param {CreateAPIContext} payload
|
|
16
18
|
*/
|
|
17
|
-
export declare function createAPIContext({ request, params, site, props, adapterName, locales, }: CreateAPIContext): APIContext;
|
|
19
|
+
export declare function createAPIContext({ request, params, site, props, adapterName, locales, routingStrategy, defaultLocale, }: CreateAPIContext): APIContext;
|
|
18
20
|
type ResponseParameters = ConstructorParameters<typeof Response>;
|
|
19
21
|
export declare class ResponseWithEncoding extends Response {
|
|
20
22
|
constructor(body: ResponseParameters[0], init: ResponseParameters[1], encoding?: BufferEncoding);
|
|
21
23
|
}
|
|
22
|
-
export declare function callEndpoint<MiddlewareResult = Response | EndpointOutput>(mod: EndpointHandler, env: Environment, ctx: RenderContext, onRequest: MiddlewareHandler<MiddlewareResult> | undefined
|
|
24
|
+
export declare function callEndpoint<MiddlewareResult = Response | EndpointOutput>(mod: EndpointHandler, env: Environment, ctx: RenderContext, onRequest: MiddlewareHandler<MiddlewareResult> | undefined): Promise<Response>;
|
|
23
25
|
export {};
|
|
@@ -4,7 +4,11 @@ import { ASTRO_VERSION } from "../constants.js";
|
|
|
4
4
|
import { AstroCookies, attachCookiesToResponse } from "../cookies/index.js";
|
|
5
5
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
6
6
|
import { callMiddleware } from "../middleware/callMiddleware.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
computeCurrentLocale,
|
|
9
|
+
computePreferredLocale,
|
|
10
|
+
computePreferredLocaleList
|
|
11
|
+
} from "../render/context.js";
|
|
8
12
|
import {} from "../render/index.js";
|
|
9
13
|
const encoder = new TextEncoder();
|
|
10
14
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
|
@@ -15,10 +19,13 @@ function createAPIContext({
|
|
|
15
19
|
site,
|
|
16
20
|
props,
|
|
17
21
|
adapterName,
|
|
18
|
-
locales
|
|
22
|
+
locales,
|
|
23
|
+
routingStrategy,
|
|
24
|
+
defaultLocale
|
|
19
25
|
}) {
|
|
20
26
|
let preferredLocale = void 0;
|
|
21
27
|
let preferredLocaleList = void 0;
|
|
28
|
+
let currentLocale = void 0;
|
|
22
29
|
const context = {
|
|
23
30
|
cookies: new AstroCookies(request),
|
|
24
31
|
request,
|
|
@@ -55,6 +62,15 @@ function createAPIContext({
|
|
|
55
62
|
}
|
|
56
63
|
return void 0;
|
|
57
64
|
},
|
|
65
|
+
get currentLocale() {
|
|
66
|
+
if (currentLocale) {
|
|
67
|
+
return currentLocale;
|
|
68
|
+
}
|
|
69
|
+
if (locales) {
|
|
70
|
+
currentLocale = computeCurrentLocale(request, locales, routingStrategy, defaultLocale);
|
|
71
|
+
}
|
|
72
|
+
return currentLocale;
|
|
73
|
+
},
|
|
58
74
|
url: new URL(request.url),
|
|
59
75
|
get clientAddress() {
|
|
60
76
|
if (clientAddressSymbol in request) {
|
|
@@ -106,14 +122,16 @@ class ResponseWithEncoding extends Response {
|
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
124
|
}
|
|
109
|
-
async function callEndpoint(mod, env, ctx, onRequest
|
|
125
|
+
async function callEndpoint(mod, env, ctx, onRequest) {
|
|
110
126
|
const context = createAPIContext({
|
|
111
127
|
request: ctx.request,
|
|
112
128
|
params: ctx.params,
|
|
113
129
|
props: ctx.props,
|
|
114
130
|
site: env.site,
|
|
115
131
|
adapterName: env.adapterName,
|
|
116
|
-
|
|
132
|
+
routingStrategy: ctx.routingStrategy,
|
|
133
|
+
defaultLocale: ctx.defaultLocale,
|
|
134
|
+
locales: ctx.locales
|
|
117
135
|
});
|
|
118
136
|
let response;
|
|
119
137
|
if (onRequest) {
|
package/dist/core/messages.js
CHANGED
|
@@ -50,7 +50,7 @@ function serverStart({
|
|
|
50
50
|
base,
|
|
51
51
|
isRestart = false
|
|
52
52
|
}) {
|
|
53
|
-
const version = "3.5.
|
|
53
|
+
const version = "3.5.6";
|
|
54
54
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
55
55
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
56
56
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -235,7 +235,7 @@ function printHelp({
|
|
|
235
235
|
message.push(
|
|
236
236
|
linebreak(),
|
|
237
237
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
238
|
-
`v${"3.5.
|
|
238
|
+
`v${"3.5.6"}`
|
|
239
239
|
)} ${headline}`
|
|
240
240
|
);
|
|
241
241
|
}
|
|
@@ -9,7 +9,9 @@ function createContext({ request, params, userDefinedLocales = [] }) {
|
|
|
9
9
|
params: params ?? {},
|
|
10
10
|
props: {},
|
|
11
11
|
site: void 0,
|
|
12
|
-
locales: userDefinedLocales
|
|
12
|
+
locales: userDefinedLocales,
|
|
13
|
+
defaultLocale: void 0,
|
|
14
|
+
routingStrategy: void 0
|
|
13
15
|
});
|
|
14
16
|
}
|
|
15
17
|
function isLocalsSerializable(value) {
|
package/dist/core/pipeline.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentInstance, MiddlewareEndpointHandler } from '../@types/astro.js';
|
|
2
2
|
import { type Environment, type RenderContext } from './render/index.js';
|
|
3
3
|
type EndpointResultHandler = (originalRequest: Request, result: Response) => Promise<Response> | Response;
|
|
4
|
+
export type PipelineHookFunction = (ctx: RenderContext, mod: ComponentInstance | undefined) => void;
|
|
4
5
|
/**
|
|
5
6
|
* This is the basic class of a pipeline.
|
|
6
7
|
*
|
|
@@ -37,5 +38,10 @@ export declare class Pipeline {
|
|
|
37
38
|
* The main function of the pipeline. Use this function to render any route known to Astro;
|
|
38
39
|
*/
|
|
39
40
|
renderRoute(renderContext: RenderContext, componentInstance: ComponentInstance | undefined): Promise<Response>;
|
|
41
|
+
/**
|
|
42
|
+
* Store a function that will be called before starting the rendering phase.
|
|
43
|
+
* @param fn
|
|
44
|
+
*/
|
|
45
|
+
onBeforeRenderRoute(fn: PipelineHookFunction): void;
|
|
40
46
|
}
|
|
41
47
|
export {};
|
package/dist/core/pipeline.js
CHANGED
|
@@ -5,6 +5,9 @@ import {} from "./render/index.js";
|
|
|
5
5
|
class Pipeline {
|
|
6
6
|
env;
|
|
7
7
|
#onRequest;
|
|
8
|
+
#hooks = {
|
|
9
|
+
before: []
|
|
10
|
+
};
|
|
8
11
|
/**
|
|
9
12
|
* The handler accepts the *original* `Request` and result returned by the endpoint.
|
|
10
13
|
* It must return a `Response`.
|
|
@@ -49,6 +52,9 @@ class Pipeline {
|
|
|
49
52
|
* The main function of the pipeline. Use this function to render any route known to Astro;
|
|
50
53
|
*/
|
|
51
54
|
async renderRoute(renderContext, componentInstance) {
|
|
55
|
+
for (const hook of this.#hooks.before) {
|
|
56
|
+
hook(renderContext, componentInstance);
|
|
57
|
+
}
|
|
52
58
|
const result = await this.#tryRenderRoute(
|
|
53
59
|
renderContext,
|
|
54
60
|
this.env,
|
|
@@ -83,7 +89,9 @@ class Pipeline {
|
|
|
83
89
|
props: renderContext.props,
|
|
84
90
|
site: env.site,
|
|
85
91
|
adapterName: env.adapterName,
|
|
86
|
-
locales: renderContext.locales
|
|
92
|
+
locales: renderContext.locales,
|
|
93
|
+
routingStrategy: renderContext.routingStrategy,
|
|
94
|
+
defaultLocale: renderContext.defaultLocale
|
|
87
95
|
});
|
|
88
96
|
switch (renderContext.route.type) {
|
|
89
97
|
case "page":
|
|
@@ -113,18 +121,19 @@ class Pipeline {
|
|
|
113
121
|
}
|
|
114
122
|
}
|
|
115
123
|
case "endpoint": {
|
|
116
|
-
return await callEndpoint(
|
|
117
|
-
mod,
|
|
118
|
-
env,
|
|
119
|
-
renderContext,
|
|
120
|
-
onRequest,
|
|
121
|
-
renderContext.locales
|
|
122
|
-
);
|
|
124
|
+
return await callEndpoint(mod, env, renderContext, onRequest);
|
|
123
125
|
}
|
|
124
126
|
default:
|
|
125
127
|
throw new Error(`Couldn't find route of type [${renderContext.route.type}]`);
|
|
126
128
|
}
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Store a function that will be called before starting the rendering phase.
|
|
132
|
+
* @param fn
|
|
133
|
+
*/
|
|
134
|
+
onBeforeRenderRoute(fn) {
|
|
135
|
+
this.#hooks.before.push(fn);
|
|
136
|
+
}
|
|
128
137
|
}
|
|
129
138
|
export {
|
|
130
139
|
Pipeline
|
|
@@ -16,6 +16,8 @@ export interface RenderContext {
|
|
|
16
16
|
props: Props;
|
|
17
17
|
locals?: object;
|
|
18
18
|
locales: string[] | undefined;
|
|
19
|
+
defaultLocale: string | undefined;
|
|
20
|
+
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
|
|
19
21
|
}
|
|
20
22
|
export type CreateRenderContextArgs = Partial<Omit<RenderContext, 'params' | 'props' | 'locals'>> & {
|
|
21
23
|
route: RouteData;
|
|
@@ -45,4 +47,5 @@ export declare function parseLocale(header: string): BrowserLocale[];
|
|
|
45
47
|
*/
|
|
46
48
|
export declare function computePreferredLocale(request: Request, locales: string[]): string | undefined;
|
|
47
49
|
export declare function computePreferredLocaleList(request: Request, locales: string[]): string[];
|
|
50
|
+
export declare function computeCurrentLocale(request: Request, locales: string[], routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined, defaultLocale: string | undefined): undefined | string;
|
|
48
51
|
export {};
|
|
@@ -18,7 +18,9 @@ async function createRenderContext(options) {
|
|
|
18
18
|
pathname,
|
|
19
19
|
params,
|
|
20
20
|
props,
|
|
21
|
-
locales: options.locales
|
|
21
|
+
locales: options.locales,
|
|
22
|
+
routingStrategy: options.routingStrategy,
|
|
23
|
+
defaultLocale: options.defaultLocale
|
|
22
24
|
};
|
|
23
25
|
Object.defineProperty(context, "locals", {
|
|
24
26
|
enumerable: true,
|
|
@@ -124,7 +126,22 @@ function computePreferredLocaleList(request, locales) {
|
|
|
124
126
|
}
|
|
125
127
|
return result;
|
|
126
128
|
}
|
|
129
|
+
function computeCurrentLocale(request, locales, routingStrategy, defaultLocale) {
|
|
130
|
+
const requestUrl = new URL(request.url);
|
|
131
|
+
for (const segment of requestUrl.pathname.split("/")) {
|
|
132
|
+
for (const locale of locales) {
|
|
133
|
+
if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
|
|
134
|
+
return locale;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (routingStrategy === "prefix-other-locales") {
|
|
139
|
+
return defaultLocale;
|
|
140
|
+
}
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
127
143
|
export {
|
|
144
|
+
computeCurrentLocale,
|
|
128
145
|
computePreferredLocale,
|
|
129
146
|
computePreferredLocaleList,
|
|
130
147
|
createRenderContext,
|
package/dist/core/render/core.js
CHANGED
|
@@ -43,7 +43,9 @@ async function renderPage({ mod, renderContext, env, cookies }) {
|
|
|
43
43
|
status: renderContext.status ?? 200,
|
|
44
44
|
cookies,
|
|
45
45
|
locals: renderContext.locals ?? {},
|
|
46
|
-
locales: renderContext.locales
|
|
46
|
+
locales: renderContext.locales,
|
|
47
|
+
defaultLocale: renderContext.defaultLocale,
|
|
48
|
+
routingStrategy: renderContext.routingStrategy
|
|
47
49
|
});
|
|
48
50
|
if (mod.frontmatter && typeof mod.frontmatter === "object" && "draft" in mod.frontmatter) {
|
|
49
51
|
env.logger.warn(
|
|
@@ -31,5 +31,7 @@ export interface CreateResultArgs {
|
|
|
31
31
|
locals: App.Locals;
|
|
32
32
|
cookies?: AstroCookies;
|
|
33
33
|
locales: string[] | undefined;
|
|
34
|
+
defaultLocale: string | undefined;
|
|
35
|
+
routingStrategy: 'prefix-always' | 'prefix-other-locales' | undefined;
|
|
34
36
|
}
|
|
35
37
|
export declare function createResult(args: CreateResultArgs): SSRResult;
|
|
@@ -3,7 +3,11 @@ import { renderJSX } from "../../runtime/server/jsx.js";
|
|
|
3
3
|
import { chunkToString } from "../../runtime/server/render/index.js";
|
|
4
4
|
import { AstroCookies } from "../cookies/index.js";
|
|
5
5
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
computeCurrentLocale,
|
|
8
|
+
computePreferredLocale,
|
|
9
|
+
computePreferredLocaleList
|
|
10
|
+
} from "./context.js";
|
|
7
11
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
|
8
12
|
const responseSentSymbol = Symbol.for("astro.responseSent");
|
|
9
13
|
function getFunctionExpression(slot) {
|
|
@@ -91,6 +95,7 @@ function createResult(args) {
|
|
|
91
95
|
let cookies = args.cookies;
|
|
92
96
|
let preferredLocale = void 0;
|
|
93
97
|
let preferredLocaleList = void 0;
|
|
98
|
+
let currentLocale = void 0;
|
|
94
99
|
const result = {
|
|
95
100
|
styles: args.styles ?? /* @__PURE__ */ new Set(),
|
|
96
101
|
scripts: args.scripts ?? /* @__PURE__ */ new Set(),
|
|
@@ -149,6 +154,23 @@ function createResult(args) {
|
|
|
149
154
|
}
|
|
150
155
|
return void 0;
|
|
151
156
|
},
|
|
157
|
+
get currentLocale() {
|
|
158
|
+
if (currentLocale) {
|
|
159
|
+
return currentLocale;
|
|
160
|
+
}
|
|
161
|
+
if (args.locales) {
|
|
162
|
+
currentLocale = computeCurrentLocale(
|
|
163
|
+
request,
|
|
164
|
+
args.locales,
|
|
165
|
+
args.routingStrategy,
|
|
166
|
+
args.defaultLocale
|
|
167
|
+
);
|
|
168
|
+
if (currentLocale) {
|
|
169
|
+
return currentLocale;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return void 0;
|
|
173
|
+
},
|
|
152
174
|
params,
|
|
153
175
|
props,
|
|
154
176
|
locals,
|
|
@@ -236,7 +236,8 @@ function createRouteManifest({ settings, cwd, fsMod }, logger) {
|
|
|
236
236
|
component,
|
|
237
237
|
generate,
|
|
238
238
|
pathname: pathname || void 0,
|
|
239
|
-
prerender
|
|
239
|
+
prerender,
|
|
240
|
+
fallbackRoutes: []
|
|
240
241
|
});
|
|
241
242
|
}
|
|
242
243
|
});
|
|
@@ -290,7 +291,8 @@ This route collides with: "${collision.component}".`
|
|
|
290
291
|
component,
|
|
291
292
|
generate,
|
|
292
293
|
pathname: pathname || void 0,
|
|
293
|
-
prerender: prerenderInjected ?? prerender
|
|
294
|
+
prerender: prerenderInjected ?? prerender,
|
|
295
|
+
fallbackRoutes: []
|
|
294
296
|
});
|
|
295
297
|
});
|
|
296
298
|
Object.entries(settings.config.redirects).forEach(([from, to]) => {
|
|
@@ -315,7 +317,8 @@ This route collides with: "${collision.component}".`
|
|
|
315
317
|
pathname: pathname || void 0,
|
|
316
318
|
prerender: false,
|
|
317
319
|
redirect: to,
|
|
318
|
-
redirectRoute: routes.find((r) => r.route === to)
|
|
320
|
+
redirectRoute: routes.find((r) => r.route === to),
|
|
321
|
+
fallbackRoutes: []
|
|
319
322
|
};
|
|
320
323
|
const lastSegmentIsDynamic = (r) => !!r.segments.at(-1)?.at(-1)?.dynamic;
|
|
321
324
|
const redirBase = path.posix.dirname(route);
|
|
@@ -414,33 +417,35 @@ This route collides with: "${collision.component}".`
|
|
|
414
417
|
if (!hasRoute) {
|
|
415
418
|
let pathname;
|
|
416
419
|
let route;
|
|
417
|
-
if (fallbackToLocale === i18n.defaultLocale) {
|
|
420
|
+
if (fallbackToLocale === i18n.defaultLocale && i18n.routingStrategy === "prefix-other-locales") {
|
|
418
421
|
if (fallbackToRoute.pathname) {
|
|
419
422
|
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
|
|
420
423
|
}
|
|
421
424
|
route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
|
|
422
425
|
} else {
|
|
423
|
-
pathname = fallbackToRoute.pathname?.replace(
|
|
424
|
-
|
|
425
|
-
`/${fallbackFromLocale}`
|
|
426
|
-
);
|
|
427
|
-
route = fallbackToRoute.route.replace(
|
|
428
|
-
`/${fallbackToLocale}`,
|
|
429
|
-
`/${fallbackFromLocale}`
|
|
430
|
-
);
|
|
426
|
+
pathname = fallbackToRoute.pathname?.replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`).replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`);
|
|
427
|
+
route = fallbackToRoute.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`).replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`);
|
|
431
428
|
}
|
|
432
429
|
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
|
433
430
|
validateSegment(s);
|
|
434
431
|
return getParts(s, route);
|
|
435
432
|
});
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
433
|
+
const generate = getRouteGenerator(segments, config.trailingSlash);
|
|
434
|
+
const index = routes.findIndex((r) => r === fallbackToRoute);
|
|
435
|
+
if (index) {
|
|
436
|
+
const fallbackRoute = {
|
|
437
|
+
...fallbackToRoute,
|
|
438
|
+
pathname,
|
|
439
|
+
route,
|
|
440
|
+
segments,
|
|
441
|
+
generate,
|
|
442
|
+
pattern: getPattern(segments, config, config.trailingSlash),
|
|
443
|
+
type: "fallback",
|
|
444
|
+
fallbackRoutes: []
|
|
445
|
+
};
|
|
446
|
+
const routeData = routes[index];
|
|
447
|
+
routeData.fallbackRoutes.push(fallbackRoute);
|
|
448
|
+
}
|
|
444
449
|
}
|
|
445
450
|
}
|
|
446
451
|
}
|
|
@@ -5,6 +5,9 @@ function serializeRouteData(routeData, trailingSlash) {
|
|
|
5
5
|
generate: void 0,
|
|
6
6
|
pattern: routeData.pattern.source,
|
|
7
7
|
redirectRoute: routeData.redirectRoute ? serializeRouteData(routeData.redirectRoute, trailingSlash) : void 0,
|
|
8
|
+
fallbackRoutes: routeData.fallbackRoutes.map((fallbackRoute) => {
|
|
9
|
+
return serializeRouteData(fallbackRoute, trailingSlash);
|
|
10
|
+
}),
|
|
8
11
|
_meta: { trailingSlash }
|
|
9
12
|
};
|
|
10
13
|
}
|
|
@@ -20,7 +23,10 @@ function deserializeRouteData(rawRouteData) {
|
|
|
20
23
|
segments: rawRouteData.segments,
|
|
21
24
|
prerender: rawRouteData.prerender,
|
|
22
25
|
redirect: rawRouteData.redirect,
|
|
23
|
-
redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0
|
|
26
|
+
redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0,
|
|
27
|
+
fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => {
|
|
28
|
+
return deserializeRouteData(fallback);
|
|
29
|
+
})
|
|
24
30
|
};
|
|
25
31
|
}
|
|
26
32
|
export {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
function matchRoute(pathname, manifest) {
|
|
2
|
-
|
|
2
|
+
const decodedPathname = decodeURI(pathname);
|
|
3
|
+
return manifest.routes.find((route) => {
|
|
4
|
+
return route.pattern.test(decodedPathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(decodedPathname));
|
|
5
|
+
});
|
|
3
6
|
}
|
|
4
7
|
function matchAllRoutes(pathname, manifest) {
|
|
5
8
|
return manifest.routes.filter((route) => route.pattern.test(pathname));
|
|
@@ -16,7 +16,7 @@ function getParams(array) {
|
|
|
16
16
|
}
|
|
17
17
|
function stringifyParams(params, route) {
|
|
18
18
|
const validatedParams = Object.entries(params).reduce((acc, next) => {
|
|
19
|
-
validateGetStaticPathsParameter(next, route.
|
|
19
|
+
validateGetStaticPathsParameter(next, route.route);
|
|
20
20
|
const [key, value] = next;
|
|
21
21
|
if (value !== void 0) {
|
|
22
22
|
acc[key] = typeof value === "string" ? trimSlashes(value) : value.toString();
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import type { MiddlewareEndpointHandler, SSRManifest } from '../@types/astro.js';
|
|
2
|
+
import type { PipelineHookFunction } from '../core/pipeline.js';
|
|
2
3
|
export declare function createI18nMiddleware(i18n: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash']): MiddlewareEndpointHandler | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* This pipeline hook attaches a `RouteData` object to the `Request`
|
|
6
|
+
*/
|
|
7
|
+
export declare const i18nPipelineHook: PipelineHookFunction;
|
package/dist/i18n/middleware.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { appendForwardSlash, joinPaths } from "@astrojs/internal-helpers/path";
|
|
2
|
+
const routeDataSymbol = Symbol.for("astro.routeData");
|
|
2
3
|
function checkIsLocaleFree(pathname, locales) {
|
|
3
4
|
for (const locale of locales) {
|
|
4
5
|
if (pathname.includes(`/${locale}`)) {
|
|
@@ -15,8 +16,14 @@ function createI18nMiddleware(i18n, base, trailingSlash) {
|
|
|
15
16
|
if (!i18n) {
|
|
16
17
|
return await next();
|
|
17
18
|
}
|
|
18
|
-
const
|
|
19
|
+
const routeData = Reflect.get(context.request, routeDataSymbol);
|
|
20
|
+
if (routeData) {
|
|
21
|
+
if (routeData.type !== "page" && routeData.type !== "fallback") {
|
|
22
|
+
return await next();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
19
25
|
const url = context.url;
|
|
26
|
+
const { locales, defaultLocale, fallback, routingStrategy } = i18n;
|
|
20
27
|
const response = await next();
|
|
21
28
|
if (response instanceof Response) {
|
|
22
29
|
const separators = url.pathname.split("/");
|
|
@@ -49,7 +56,7 @@ function createI18nMiddleware(i18n, base, trailingSlash) {
|
|
|
49
56
|
if (urlLocale && fallbackKeys.includes(urlLocale)) {
|
|
50
57
|
const fallbackLocale = fallback[urlLocale];
|
|
51
58
|
let newPathname;
|
|
52
|
-
if (fallbackLocale === defaultLocale) {
|
|
59
|
+
if (fallbackLocale === defaultLocale && routingStrategy === "prefix-other-locales") {
|
|
53
60
|
newPathname = url.pathname.replace(`/${urlLocale}`, ``);
|
|
54
61
|
} else {
|
|
55
62
|
newPathname = url.pathname.replace(`/${urlLocale}`, `/${fallbackLocale}`);
|
|
@@ -61,6 +68,10 @@ function createI18nMiddleware(i18n, base, trailingSlash) {
|
|
|
61
68
|
return response;
|
|
62
69
|
};
|
|
63
70
|
}
|
|
71
|
+
const i18nPipelineHook = (ctx) => {
|
|
72
|
+
Reflect.set(ctx.request, routeDataSymbol, ctx.route);
|
|
73
|
+
};
|
|
64
74
|
export {
|
|
65
|
-
createI18nMiddleware
|
|
75
|
+
createI18nMiddleware,
|
|
76
|
+
i18nPipelineHook
|
|
66
77
|
};
|
|
@@ -13,7 +13,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
13
13
|
{ DevOverlayHighlight },
|
|
14
14
|
{ DevOverlayTooltip },
|
|
15
15
|
{ DevOverlayWindow },
|
|
16
|
-
{ DevOverlayToggle }
|
|
16
|
+
{ DevOverlayToggle },
|
|
17
|
+
{ getIconElement, isDefinedIcon }
|
|
17
18
|
] = await Promise.all([
|
|
18
19
|
// @ts-expect-error
|
|
19
20
|
import("astro:dev-overlay"),
|
|
@@ -26,7 +27,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
26
27
|
import("./ui-library/highlight.js"),
|
|
27
28
|
import("./ui-library/tooltip.js"),
|
|
28
29
|
import("./ui-library/window.js"),
|
|
29
|
-
import("./ui-library/toggle.js")
|
|
30
|
+
import("./ui-library/toggle.js"),
|
|
31
|
+
import("./ui-library/icons.js")
|
|
30
32
|
]);
|
|
31
33
|
customElements.define("astro-dev-overlay", AstroDevOverlay);
|
|
32
34
|
customElements.define("astro-dev-overlay-window", DevOverlayWindow);
|
|
@@ -43,6 +45,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
43
45
|
builtIn,
|
|
44
46
|
active: false,
|
|
45
47
|
status: "loading",
|
|
48
|
+
notification: { state: false },
|
|
46
49
|
eventTarget
|
|
47
50
|
};
|
|
48
51
|
eventTarget.addEventListener("toggle-notification", (evt) => {
|
|
@@ -53,7 +56,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
53
56
|
if (evt instanceof CustomEvent) {
|
|
54
57
|
newState = evt.detail.state ?? true;
|
|
55
58
|
}
|
|
56
|
-
|
|
59
|
+
plugin.notification.state = newState;
|
|
60
|
+
if (settings.config.disablePluginNotification === false) {
|
|
57
61
|
target.querySelector(".notification")?.toggleAttribute("data-active", newState);
|
|
58
62
|
}
|
|
59
63
|
});
|
|
@@ -66,11 +70,148 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
66
70
|
});
|
|
67
71
|
return plugin;
|
|
68
72
|
};
|
|
73
|
+
const astromorePlugin = {
|
|
74
|
+
id: "astro:more",
|
|
75
|
+
name: "More",
|
|
76
|
+
icon: "dots-three",
|
|
77
|
+
init(canvas, eventTarget) {
|
|
78
|
+
const hiddenPlugins = plugins.filter((p) => !p.builtIn).slice(overlay.customPluginsToShow);
|
|
79
|
+
createDropdown();
|
|
80
|
+
document.addEventListener("astro:after-swap", createDropdown);
|
|
81
|
+
function createDropdown() {
|
|
82
|
+
const style = document.createElement("style");
|
|
83
|
+
style.innerHTML = `
|
|
84
|
+
#dropdown {
|
|
85
|
+
background: rgba(19, 21, 26, 1);
|
|
86
|
+
border: 1px solid rgba(52, 56, 65, 1);
|
|
87
|
+
border-radius: 12px;
|
|
88
|
+
box-shadow: 0px 0px 0px 0px rgba(19, 21, 26, 0.30), 0px 1px 2px 0px rgba(19, 21, 26, 0.29), 0px 4px 4px 0px rgba(19, 21, 26, 0.26), 0px 10px 6px 0px rgba(19, 21, 26, 0.15), 0px 17px 7px 0px rgba(19, 21, 26, 0.04), 0px 26px 7px 0px rgba(19, 21, 26, 0.01);
|
|
89
|
+
width: 180px;
|
|
90
|
+
padding: 8px;
|
|
91
|
+
z-index: 9999999999;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.notification {
|
|
95
|
+
display: none;
|
|
96
|
+
position: absolute;
|
|
97
|
+
top: -4px;
|
|
98
|
+
right: -6px;
|
|
99
|
+
width: 8px;
|
|
100
|
+
height: 8px;
|
|
101
|
+
border-radius: 9999px;
|
|
102
|
+
border: 1px solid rgba(19, 21, 26, 1);
|
|
103
|
+
background: #B33E66;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.notification[data-active] {
|
|
107
|
+
display: block;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#dropdown button {
|
|
111
|
+
border: 0;
|
|
112
|
+
background: transparent;
|
|
113
|
+
color: white;
|
|
114
|
+
font-family: system-ui, sans-serif;
|
|
115
|
+
font-size: 16px;
|
|
116
|
+
line-height: 1.2;
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
text-decoration: none;
|
|
119
|
+
margin: 0;
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
width: 100%;
|
|
123
|
+
padding: 8px;
|
|
124
|
+
border-radius: 8px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
#dropdown button:hover, #dropdown button:focus-visible {
|
|
128
|
+
background: rgba(27, 30, 36, 1);
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#dropdown button.active {
|
|
133
|
+
background: rgba(71, 78, 94, 1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#dropdown .icon {
|
|
137
|
+
position: relative;
|
|
138
|
+
height: 24px;
|
|
139
|
+
width: 24px;
|
|
140
|
+
margin-right: 0.5em;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#dropdown .icon svg {
|
|
144
|
+
max-height: 100%;
|
|
145
|
+
max-width: 100%;
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
canvas.append(style);
|
|
149
|
+
const dropdown = document.createElement("div");
|
|
150
|
+
dropdown.id = "dropdown";
|
|
151
|
+
for (const plugin of hiddenPlugins) {
|
|
152
|
+
const buttonContainer = document.createElement("div");
|
|
153
|
+
buttonContainer.classList.add("item");
|
|
154
|
+
const button = document.createElement("button");
|
|
155
|
+
button.setAttribute("data-plugin-id", plugin.id);
|
|
156
|
+
const iconContainer = document.createElement("div");
|
|
157
|
+
const iconElement = getPluginIcon(plugin.icon);
|
|
158
|
+
iconContainer.append(iconElement);
|
|
159
|
+
const notification = document.createElement("div");
|
|
160
|
+
notification.classList.add("notification");
|
|
161
|
+
iconContainer.append(notification);
|
|
162
|
+
iconContainer.classList.add("icon");
|
|
163
|
+
button.append(iconContainer);
|
|
164
|
+
button.append(document.createTextNode(plugin.name));
|
|
165
|
+
button.addEventListener("click", () => {
|
|
166
|
+
overlay.togglePluginStatus(plugin);
|
|
167
|
+
});
|
|
168
|
+
buttonContainer.append(button);
|
|
169
|
+
dropdown.append(buttonContainer);
|
|
170
|
+
eventTarget.addEventListener("plugin-toggled", positionDropdown);
|
|
171
|
+
window.addEventListener("resize", positionDropdown);
|
|
172
|
+
plugin.eventTarget.addEventListener("toggle-notification", (evt) => {
|
|
173
|
+
if (!(evt instanceof CustomEvent))
|
|
174
|
+
return;
|
|
175
|
+
if (settings.config.disablePluginNotification === false) {
|
|
176
|
+
notification.toggleAttribute("data-active", evt.detail.state ?? true);
|
|
177
|
+
}
|
|
178
|
+
eventTarget.dispatchEvent(
|
|
179
|
+
new CustomEvent("toggle-notification", {
|
|
180
|
+
detail: {
|
|
181
|
+
state: hiddenPlugins.some((p) => p.notification.state === true)
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
canvas.append(dropdown);
|
|
188
|
+
function getPluginIcon(icon) {
|
|
189
|
+
if (isDefinedIcon(icon)) {
|
|
190
|
+
return getIconElement(icon);
|
|
191
|
+
}
|
|
192
|
+
return icon;
|
|
193
|
+
}
|
|
194
|
+
function positionDropdown() {
|
|
195
|
+
const moreButtonRect = overlay.shadowRoot.querySelector('[data-plugin-id="astro:more"]')?.getBoundingClientRect();
|
|
196
|
+
const dropdownRect = dropdown.getBoundingClientRect();
|
|
197
|
+
if (moreButtonRect && dropdownRect) {
|
|
198
|
+
dropdown.style.position = "absolute";
|
|
199
|
+
dropdown.style.top = `${moreButtonRect.top - dropdownRect.height - 12}px`;
|
|
200
|
+
dropdown.style.left = `${moreButtonRect.left + moreButtonRect.width - dropdownRect.width}px`;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
69
206
|
const customPluginsDefinitions = await loadDevOverlayPlugins();
|
|
70
207
|
const plugins = [
|
|
71
|
-
...[
|
|
72
|
-
|
|
73
|
-
|
|
208
|
+
...[
|
|
209
|
+
astroDevToolPlugin,
|
|
210
|
+
astroXrayPlugin,
|
|
211
|
+
astroAuditPlugin,
|
|
212
|
+
astroSettingsPlugin,
|
|
213
|
+
astromorePlugin
|
|
214
|
+
].map((pluginDef) => preparePlugin(pluginDef, true)),
|
|
74
215
|
...customPluginsDefinitions.map((pluginDef) => preparePlugin(pluginDef, false))
|
|
75
216
|
];
|
|
76
217
|
overlay.plugins = plugins;
|