astro 3.4.4 → 3.5.0
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/client.d.ts +86 -0
- package/components/Code.astro +15 -2
- package/components/Picture.astro +2 -1
- package/components/ViewTransitions.astro +39 -38
- package/content-module.template.mjs +4 -14
- package/dist/@types/astro.d.ts +222 -5
- package/dist/assets/build/generate.d.ts +2 -1
- package/dist/assets/build/generate.js +16 -5
- package/dist/assets/consts.d.ts +1 -0
- package/dist/assets/consts.js +2 -0
- package/dist/assets/endpoint/generic.js +6 -2
- package/dist/assets/internal.js +9 -2
- package/dist/assets/services/service.d.ts +8 -3
- package/dist/assets/services/service.js +2 -1
- package/dist/assets/services/vendor/squoosh/image-pool.d.ts +1 -2
- package/dist/assets/types.d.ts +9 -5
- package/dist/assets/utils/emitAsset.js +5 -0
- package/dist/assets/utils/metadata.d.ts +1 -2
- package/dist/assets/utils/proxy.d.ts +1 -0
- package/dist/assets/utils/proxy.js +16 -0
- package/dist/assets/utils/queryParams.d.ts +1 -1
- package/dist/assets/utils/transformToPath.d.ts +1 -1
- package/dist/assets/utils/transformToPath.js +8 -3
- package/dist/assets/vite-plugin-assets.js +26 -11
- package/dist/cli/build/index.js +1 -1
- package/dist/content/consts.d.ts +1 -0
- package/dist/content/consts.js +2 -0
- package/dist/content/runtime-assets.d.ts +9 -1
- package/dist/content/runtime-assets.js +1 -1
- package/dist/content/runtime.d.ts +1 -0
- package/dist/content/runtime.js +8 -2
- package/dist/content/utils.d.ts +1 -0
- package/dist/content/utils.js +9 -0
- package/dist/content/vite-plugin-content-assets.js +49 -23
- package/dist/content/vite-plugin-content-imports.js +9 -3
- package/dist/content/vite-plugin-content-virtual-mod.d.ts +17 -12
- package/dist/content/vite-plugin-content-virtual-mod.js +136 -57
- package/dist/core/app/index.js +19 -4
- package/dist/core/app/types.d.ts +7 -1
- package/dist/core/build/buildPipeline.js +17 -4
- package/dist/core/build/common.js +2 -0
- package/dist/core/build/generate.js +64 -34
- package/dist/core/build/index.d.ts +0 -8
- package/dist/core/build/index.js +9 -2
- package/dist/core/build/internal.d.ts +11 -1
- package/dist/core/build/internal.js +23 -1
- package/dist/core/build/page-data.js +46 -18
- package/dist/core/build/plugin.d.ts +12 -10
- package/dist/core/build/plugin.js +14 -22
- package/dist/core/build/plugins/index.js +4 -0
- package/dist/core/build/plugins/plugin-alias-resolve.js +1 -1
- package/dist/core/build/plugins/plugin-analyzer.js +1 -1
- package/dist/core/build/plugins/plugin-chunks.d.ts +4 -0
- package/dist/core/build/plugins/plugin-chunks.js +31 -0
- package/dist/core/build/plugins/plugin-component-entry.js +1 -1
- package/dist/core/build/plugins/plugin-content.d.ts +4 -0
- package/dist/core/build/plugins/plugin-content.js +273 -0
- package/dist/core/build/plugins/plugin-css.js +9 -4
- package/dist/core/build/plugins/plugin-hoisted-scripts.js +1 -1
- package/dist/core/build/plugins/plugin-internals.js +1 -1
- package/dist/core/build/plugins/plugin-manifest.js +14 -5
- package/dist/core/build/plugins/plugin-middleware.d.ts +1 -3
- package/dist/core/build/plugins/plugin-middleware.js +5 -57
- package/dist/core/build/plugins/plugin-pages.js +3 -3
- package/dist/core/build/plugins/plugin-prerender.js +2 -5
- package/dist/core/build/plugins/plugin-renderers.js +1 -1
- package/dist/core/build/plugins/plugin-ssr.js +6 -5
- package/dist/core/build/plugins/util.d.ts +3 -3
- package/dist/core/build/static-build.d.ts +2 -1
- package/dist/core/build/static-build.js +52 -28
- package/dist/core/build/types.d.ts +1 -1
- package/dist/core/build/util.d.ts +7 -0
- package/dist/core/build/util.js +37 -1
- package/dist/core/compile/compile.js +1 -0
- package/dist/core/config/config.js +3 -0
- package/dist/core/config/schema.d.ts +208 -0
- package/dist/core/config/schema.js +55 -2
- package/dist/core/config/settings.js +1 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +9 -3
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/endpoint/index.d.ts +4 -3
- package/dist/core/endpoint/index.js +29 -3
- package/dist/core/errors/errors-data.d.ts +11 -0
- package/dist/core/errors/errors-data.js +17 -0
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/index.d.ts +7 -3
- package/dist/core/middleware/index.js +3 -2
- package/dist/core/middleware/loadMiddleware.d.ts +1 -2
- package/dist/core/middleware/loadMiddleware.js +3 -4
- package/dist/core/middleware/sequence.d.ts +2 -2
- package/dist/core/middleware/sequence.js +3 -2
- package/dist/core/middleware/vite-plugin.d.ts +9 -0
- package/dist/core/middleware/vite-plugin.js +101 -0
- package/dist/core/pipeline.d.ts +1 -1
- package/dist/core/pipeline.js +6 -4
- package/dist/core/redirects/helpers.d.ts +1 -0
- package/dist/core/redirects/helpers.js +4 -0
- package/dist/core/render/context.d.ts +24 -1
- package/dist/core/render/context.js +96 -2
- package/dist/core/render/core.d.ts +2 -14
- package/dist/core/render/core.js +12 -52
- package/dist/core/render/index.d.ts +2 -3
- package/dist/core/render/index.js +3 -4
- package/dist/core/render/params-and-props.d.ts +1 -1
- package/dist/core/render/params-and-props.js +5 -2
- package/dist/core/render/result.d.ts +1 -0
- package/dist/core/render/result.js +23 -0
- package/dist/core/render/route-cache.d.ts +1 -1
- package/dist/core/render/route-cache.js +17 -11
- package/dist/core/routing/manifest/create.js +118 -4
- package/dist/core/sync/index.d.ts +2 -24
- package/dist/i18n/index.d.ts +54 -0
- package/dist/i18n/index.js +91 -0
- package/dist/i18n/middleware.d.ts +2 -0
- package/dist/i18n/middleware.js +62 -0
- package/dist/i18n/vite-plugin-i18n.d.ts +7 -0
- package/dist/i18n/vite-plugin-i18n.js +62 -0
- package/dist/integrations/astroFeaturesValidation.js +4 -1
- package/dist/integrations/index.js +12 -0
- package/dist/prefetch/index.d.ts +31 -0
- package/dist/prefetch/index.js +176 -0
- package/dist/prefetch/vite-plugin-prefetch.d.ts +5 -0
- package/dist/prefetch/vite-plugin-prefetch.js +43 -0
- package/dist/runtime/client/dev-overlay/plugins/audit.js +17 -9
- package/dist/runtime/server/index.d.ts +0 -2
- package/dist/runtime/server/render/component.js +3 -5
- package/dist/transitions/router.d.ts +1 -0
- package/dist/transitions/router.js +9 -4
- package/dist/transitions/vite-plugin-transitions.d.ts +4 -1
- package/dist/transitions/vite-plugin-transitions.js +7 -1
- package/dist/vite-plugin-astro-server/devPipeline.d.ts +1 -0
- package/dist/vite-plugin-astro-server/devPipeline.js +2 -0
- package/dist/vite-plugin-astro-server/plugin.js +11 -1
- package/dist/vite-plugin-astro-server/route.js +113 -51
- package/dist/vite-plugin-head/index.js +1 -1
- package/dist/vite-plugin-markdown/index.js +1 -0
- package/package.json +7 -5
- package/tsconfigs/base.json +1 -1
- package/dist/core/endpoint/dev/index.d.ts +0 -2
- package/dist/core/endpoint/dev/index.js +0 -17
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { AstroMiddlewareInstance, ComponentInstance, RouteData } from '../../@types/astro.js';
|
|
2
2
|
import type { Environment } from './environment.js';
|
|
3
|
-
export { createRenderContext } from './context.js';
|
|
3
|
+
export { computePreferredLocale, createRenderContext } from './context.js';
|
|
4
4
|
export type { RenderContext } from './context.js';
|
|
5
|
-
export { tryRenderRoute } from './core.js';
|
|
6
5
|
export { createEnvironment } from './environment.js';
|
|
7
6
|
export { getParamsAndProps } from './params-and-props.js';
|
|
8
7
|
export { loadRenderer } from './renderer.js';
|
|
@@ -18,7 +17,7 @@ export interface SSROptions {
|
|
|
18
17
|
preload: ComponentInstance;
|
|
19
18
|
/** Request */
|
|
20
19
|
request: Request;
|
|
21
|
-
/** optional, in case we need to render something outside
|
|
20
|
+
/** optional, in case we need to render something outside a dev server */
|
|
22
21
|
route: RouteData;
|
|
23
22
|
/**
|
|
24
23
|
* Optional middlewares
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { createRenderContext } from "./context.js";
|
|
2
|
-
import { tryRenderRoute } from "./core.js";
|
|
1
|
+
import { computePreferredLocale, createRenderContext } from "./context.js";
|
|
3
2
|
import { createEnvironment } from "./environment.js";
|
|
4
3
|
import { getParamsAndProps } from "./params-and-props.js";
|
|
5
4
|
import { loadRenderer } from "./renderer.js";
|
|
6
5
|
export {
|
|
6
|
+
computePreferredLocale,
|
|
7
7
|
createEnvironment,
|
|
8
8
|
createRenderContext,
|
|
9
9
|
getParamsAndProps,
|
|
10
|
-
loadRenderer
|
|
11
|
-
tryRenderRoute
|
|
10
|
+
loadRenderer
|
|
12
11
|
};
|
|
@@ -2,7 +2,7 @@ import type { ComponentInstance, Params, Props, RouteData } from '../../@types/a
|
|
|
2
2
|
import type { Logger } from '../logger/core.js';
|
|
3
3
|
import { RouteCache } from './route-cache.js';
|
|
4
4
|
interface GetParamsAndPropsOptions {
|
|
5
|
-
mod: ComponentInstance;
|
|
5
|
+
mod: ComponentInstance | undefined;
|
|
6
6
|
route?: RouteData | undefined;
|
|
7
7
|
routeCache: RouteCache;
|
|
8
8
|
pathname: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
2
|
+
import { routeIsFallback } from "../redirects/helpers.js";
|
|
2
3
|
import { routeIsRedirect } from "../redirects/index.js";
|
|
3
4
|
import { getParams } from "../routing/params.js";
|
|
4
5
|
import { RouteCache, callGetStaticPaths, findPathItemByKey } from "./route-cache.js";
|
|
@@ -8,10 +9,12 @@ async function getParamsAndProps(opts) {
|
|
|
8
9
|
return [{}, {}];
|
|
9
10
|
}
|
|
10
11
|
const params = getRouteParams(route, pathname) ?? {};
|
|
11
|
-
if (routeIsRedirect(route)) {
|
|
12
|
+
if (routeIsRedirect(route) || routeIsFallback(route)) {
|
|
12
13
|
return [params, {}];
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
if (mod) {
|
|
16
|
+
validatePrerenderEndpointCollision(route, mod, params);
|
|
17
|
+
}
|
|
15
18
|
const staticPaths = await callGetStaticPaths({
|
|
16
19
|
mod,
|
|
17
20
|
route,
|
|
@@ -3,6 +3,7 @@ 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 { computePreferredLocale, computePreferredLocaleList } from "./context.js";
|
|
6
7
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
|
7
8
|
const responseSentSymbol = Symbol.for("astro.responseSent");
|
|
8
9
|
function getFunctionExpression(slot) {
|
|
@@ -88,6 +89,8 @@ function createResult(args) {
|
|
|
88
89
|
writable: false
|
|
89
90
|
});
|
|
90
91
|
let cookies = args.cookies;
|
|
92
|
+
let preferredLocale = void 0;
|
|
93
|
+
let preferredLocaleList = void 0;
|
|
91
94
|
const result = {
|
|
92
95
|
styles: args.styles ?? /* @__PURE__ */ new Set(),
|
|
93
96
|
scripts: args.scripts ?? /* @__PURE__ */ new Set(),
|
|
@@ -126,6 +129,26 @@ function createResult(args) {
|
|
|
126
129
|
result.cookies = cookies;
|
|
127
130
|
return cookies;
|
|
128
131
|
},
|
|
132
|
+
get preferredLocale() {
|
|
133
|
+
if (preferredLocale) {
|
|
134
|
+
return preferredLocale;
|
|
135
|
+
}
|
|
136
|
+
if (args.locales) {
|
|
137
|
+
preferredLocale = computePreferredLocale(request, args.locales);
|
|
138
|
+
return preferredLocale;
|
|
139
|
+
}
|
|
140
|
+
return void 0;
|
|
141
|
+
},
|
|
142
|
+
get preferredLocaleList() {
|
|
143
|
+
if (preferredLocaleList) {
|
|
144
|
+
return preferredLocaleList;
|
|
145
|
+
}
|
|
146
|
+
if (args.locales) {
|
|
147
|
+
preferredLocaleList = computePreferredLocaleList(request, args.locales);
|
|
148
|
+
return preferredLocaleList;
|
|
149
|
+
}
|
|
150
|
+
return void 0;
|
|
151
|
+
},
|
|
129
152
|
params,
|
|
130
153
|
props,
|
|
131
154
|
locals,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentInstance, GetStaticPathsItem, GetStaticPathsResultKeyed, Params, RouteData, RuntimeMode } from '../../@types/astro.js';
|
|
2
2
|
import type { Logger } from '../logger/core.js';
|
|
3
3
|
interface CallGetStaticPathsOptions {
|
|
4
|
-
mod: ComponentInstance;
|
|
4
|
+
mod: ComponentInstance | undefined;
|
|
5
5
|
route: RouteData;
|
|
6
6
|
routeCache: RouteCache;
|
|
7
7
|
logger: Logger;
|
|
@@ -12,24 +12,30 @@ async function callGetStaticPaths({
|
|
|
12
12
|
const cached = routeCache.get(route);
|
|
13
13
|
if (cached?.staticPaths)
|
|
14
14
|
return cached.staticPaths;
|
|
15
|
-
|
|
15
|
+
if (mod) {
|
|
16
|
+
validateDynamicRouteModule(mod, { ssr, route });
|
|
17
|
+
}
|
|
16
18
|
if (ssr && !route.prerender) {
|
|
17
19
|
const entry = Object.assign([], { keyed: /* @__PURE__ */ new Map() });
|
|
18
20
|
routeCache.set(route, { ...cached, staticPaths: entry });
|
|
19
21
|
return entry;
|
|
20
22
|
}
|
|
21
|
-
if (!mod.getStaticPaths) {
|
|
22
|
-
throw new Error("Unexpected Error.");
|
|
23
|
-
}
|
|
24
23
|
let staticPaths = [];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
paginate: generatePaginateFunction(route),
|
|
29
|
-
rss() {
|
|
30
|
-
throw new AstroError(AstroErrorData.GetStaticPathsRemovedRSSHelper);
|
|
24
|
+
if (mod) {
|
|
25
|
+
if (!mod.getStaticPaths) {
|
|
26
|
+
throw new Error("Unexpected Error.");
|
|
31
27
|
}
|
|
32
|
-
|
|
28
|
+
if (mod) {
|
|
29
|
+
staticPaths = await mod.getStaticPaths({
|
|
30
|
+
// Q: Why the cast?
|
|
31
|
+
// A: So users downstream can have nicer typings, we have to make some sacrifice in our internal typings, which necessitate a cast here
|
|
32
|
+
paginate: generatePaginateFunction(route),
|
|
33
|
+
rss() {
|
|
34
|
+
throw new AstroError(AstroErrorData.GetStaticPathsRemovedRSSHelper);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
33
39
|
validateGetStaticPathsResult(staticPaths, logger, route);
|
|
34
40
|
const keyedStaticPaths = staticPaths;
|
|
35
41
|
keyedStaticPaths.keyed = /* @__PURE__ */ new Map();
|
|
@@ -34,7 +34,9 @@ function getParts(part, file) {
|
|
|
34
34
|
});
|
|
35
35
|
return result;
|
|
36
36
|
}
|
|
37
|
-
function getPattern(segments,
|
|
37
|
+
function getPattern(segments, config) {
|
|
38
|
+
const base = config.base;
|
|
39
|
+
const addTrailingSlash = config.trailingSlash;
|
|
38
40
|
const pathname = segments.map((segment) => {
|
|
39
41
|
if (segment.length === 1 && segment[0].spread) {
|
|
40
42
|
return "(?:\\/(.*?))?";
|
|
@@ -222,7 +224,7 @@ function createRouteManifest({ settings, cwd, fsMod }, logger) {
|
|
|
222
224
|
components.push(item.file);
|
|
223
225
|
const component = item.file;
|
|
224
226
|
const trailingSlash = item.isPage ? settings.config.trailingSlash : "never";
|
|
225
|
-
const pattern = getPattern(segments, settings.config
|
|
227
|
+
const pattern = getPattern(segments, settings.config);
|
|
226
228
|
const generate = getRouteGenerator(segments, trailingSlash);
|
|
227
229
|
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
|
228
230
|
const route = `/${segments.map(([{ dynamic, content }]) => dynamic ? `[${content}]` : content).join("/")}`.toLowerCase();
|
|
@@ -268,7 +270,7 @@ function createRouteManifest({ settings, cwd, fsMod }, logger) {
|
|
|
268
270
|
const type = resolved.endsWith(".astro") ? "page" : "endpoint";
|
|
269
271
|
const isPage = type === "page";
|
|
270
272
|
const trailingSlash = isPage ? config.trailingSlash : "never";
|
|
271
|
-
const pattern = getPattern(segments, settings.config
|
|
273
|
+
const pattern = getPattern(segments, settings.config);
|
|
272
274
|
const generate = getRouteGenerator(segments, trailingSlash);
|
|
273
275
|
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
|
274
276
|
const params = segments.flat().filter((p) => p.dynamic).map((p) => p.content);
|
|
@@ -298,7 +300,7 @@ This route collides with: "${collision.component}".`
|
|
|
298
300
|
validateSegment(s);
|
|
299
301
|
return getParts(s, from);
|
|
300
302
|
});
|
|
301
|
-
const pattern = getPattern(segments, settings.config
|
|
303
|
+
const pattern = getPattern(segments, settings.config);
|
|
302
304
|
const generate = getRouteGenerator(segments, trailingSlash);
|
|
303
305
|
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
|
304
306
|
const params = segments.flat().filter((p) => p.dynamic).map((p) => p.content);
|
|
@@ -334,6 +336,118 @@ This route collides with: "${collision.component}".`
|
|
|
334
336
|
}
|
|
335
337
|
routes.push(routeData);
|
|
336
338
|
});
|
|
339
|
+
const i18n = settings.config.experimental.i18n;
|
|
340
|
+
if (i18n) {
|
|
341
|
+
const routesByLocale = /* @__PURE__ */ new Map();
|
|
342
|
+
const setRoutes = new Set(routes);
|
|
343
|
+
for (const locale of i18n.locales.filter((loc) => loc !== i18n.defaultLocale)) {
|
|
344
|
+
for (const route of setRoutes) {
|
|
345
|
+
if (!route.route.includes(`/${locale}`)) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
const currentRoutes = routesByLocale.get(locale);
|
|
349
|
+
if (currentRoutes) {
|
|
350
|
+
currentRoutes.push(route);
|
|
351
|
+
routesByLocale.set(locale, currentRoutes);
|
|
352
|
+
} else {
|
|
353
|
+
routesByLocale.set(locale, [route]);
|
|
354
|
+
}
|
|
355
|
+
setRoutes.delete(route);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
for (const route of setRoutes) {
|
|
359
|
+
const currentRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
360
|
+
if (currentRoutes) {
|
|
361
|
+
currentRoutes.push(route);
|
|
362
|
+
routesByLocale.set(i18n.defaultLocale, currentRoutes);
|
|
363
|
+
} else {
|
|
364
|
+
routesByLocale.set(i18n.defaultLocale, [route]);
|
|
365
|
+
}
|
|
366
|
+
setRoutes.delete(route);
|
|
367
|
+
}
|
|
368
|
+
if (i18n.routingStrategy === "prefix-always") {
|
|
369
|
+
const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
370
|
+
if (defaultLocaleRoutes) {
|
|
371
|
+
const indexDefaultRoute = defaultLocaleRoutes.find((routeData) => {
|
|
372
|
+
return routeData.component.includes("index");
|
|
373
|
+
});
|
|
374
|
+
if (indexDefaultRoute) {
|
|
375
|
+
const pathname = "/";
|
|
376
|
+
const route = "/";
|
|
377
|
+
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
|
378
|
+
validateSegment(s);
|
|
379
|
+
return getParts(s, route);
|
|
380
|
+
});
|
|
381
|
+
routes.push({
|
|
382
|
+
...indexDefaultRoute,
|
|
383
|
+
pathname,
|
|
384
|
+
route,
|
|
385
|
+
segments,
|
|
386
|
+
pattern: getPattern(segments, config),
|
|
387
|
+
type: "fallback"
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (i18n.fallback) {
|
|
393
|
+
let fallback = Object.entries(i18n.fallback);
|
|
394
|
+
if (fallback.length > 0) {
|
|
395
|
+
for (const [fallbackFromLocale, fallbackToLocale] of fallback) {
|
|
396
|
+
let fallbackToRoutes;
|
|
397
|
+
if (fallbackToLocale === i18n.defaultLocale) {
|
|
398
|
+
fallbackToRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
399
|
+
} else {
|
|
400
|
+
fallbackToRoutes = routesByLocale.get(fallbackToLocale);
|
|
401
|
+
}
|
|
402
|
+
const fallbackFromRoutes = routesByLocale.get(fallbackFromLocale);
|
|
403
|
+
if (!fallbackToRoutes) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
for (const fallbackToRoute of fallbackToRoutes) {
|
|
407
|
+
const hasRoute = fallbackFromRoutes && // we check if the fallback from locale (the origin) has already this route
|
|
408
|
+
fallbackFromRoutes.some((route) => {
|
|
409
|
+
if (fallbackToLocale === i18n.defaultLocale) {
|
|
410
|
+
return route.route.replace(`/${fallbackFromLocale}`, "") === fallbackToRoute.route;
|
|
411
|
+
} else {
|
|
412
|
+
return route.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`) === fallbackToRoute.route;
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
if (!hasRoute) {
|
|
416
|
+
let pathname;
|
|
417
|
+
let route;
|
|
418
|
+
if (fallbackToLocale === i18n.defaultLocale) {
|
|
419
|
+
if (fallbackToRoute.pathname) {
|
|
420
|
+
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
|
|
421
|
+
}
|
|
422
|
+
route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
|
|
423
|
+
} else {
|
|
424
|
+
pathname = fallbackToRoute.pathname?.replace(
|
|
425
|
+
`/${fallbackToLocale}`,
|
|
426
|
+
`/${fallbackFromLocale}`
|
|
427
|
+
);
|
|
428
|
+
route = fallbackToRoute.route.replace(
|
|
429
|
+
`/${fallbackToLocale}`,
|
|
430
|
+
`/${fallbackFromLocale}`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
|
434
|
+
validateSegment(s);
|
|
435
|
+
return getParts(s, route);
|
|
436
|
+
});
|
|
437
|
+
routes.push({
|
|
438
|
+
...fallbackToRoute,
|
|
439
|
+
pathname,
|
|
440
|
+
route,
|
|
441
|
+
segments,
|
|
442
|
+
pattern: getPattern(segments, config),
|
|
443
|
+
type: "fallback"
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
337
451
|
return {
|
|
338
452
|
routes
|
|
339
453
|
};
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import fsMod from 'node:fs';
|
|
3
|
-
import type { AstroInlineConfig, AstroSettings } from '../../@types/astro.js';
|
|
1
|
+
import type { AstroInlineConfig } from '../../@types/astro.js';
|
|
4
2
|
import type { Logger } from '../logger/core.js';
|
|
5
3
|
export type ProcessExit = 0 | 1;
|
|
6
|
-
export type SyncOptions = {
|
|
7
|
-
/**
|
|
8
|
-
* @internal only used for testing
|
|
9
|
-
*/
|
|
10
|
-
fs?: typeof fsMod;
|
|
11
|
-
};
|
|
4
|
+
export type SyncOptions = {};
|
|
12
5
|
export type SyncInternalOptions = SyncOptions & {
|
|
13
6
|
logger: Logger;
|
|
14
7
|
};
|
|
@@ -19,18 +12,3 @@ export type SyncInternalOptions = SyncOptions & {
|
|
|
19
12
|
* @experimental The JavaScript API is experimental
|
|
20
13
|
*/
|
|
21
14
|
export default function sync(inlineConfig: AstroInlineConfig, options?: SyncOptions): Promise<ProcessExit>;
|
|
22
|
-
/**
|
|
23
|
-
* Generate content collection types, and then returns the process exit signal.
|
|
24
|
-
*
|
|
25
|
-
* A non-zero process signal is emitted in case there's an error while generating content collection types.
|
|
26
|
-
*
|
|
27
|
-
* This should only be used when the callee already has an `AstroSetting`, otherwise use `sync()` instead.
|
|
28
|
-
* @internal
|
|
29
|
-
*
|
|
30
|
-
* @param {SyncOptions} options
|
|
31
|
-
* @param {AstroSettings} settings Astro settings
|
|
32
|
-
* @param {typeof fsMod} options.fs The file system
|
|
33
|
-
* @param {LogOptions} options.logging Logging options
|
|
34
|
-
* @return {Promise<ProcessExit>}
|
|
35
|
-
*/
|
|
36
|
-
export declare function syncInternal(settings: AstroSettings, { logger, fs }: SyncInternalOptions): Promise<ProcessExit>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AstroConfig } from '../@types/astro.js';
|
|
2
|
+
type GetLocaleRelativeUrl = GetLocaleOptions & {
|
|
3
|
+
locale: string;
|
|
4
|
+
base: string;
|
|
5
|
+
locales: string[];
|
|
6
|
+
trailingSlash: AstroConfig['trailingSlash'];
|
|
7
|
+
format: AstroConfig['build']['format'];
|
|
8
|
+
routingStrategy?: 'prefix-always' | 'prefix-other-locales';
|
|
9
|
+
defaultLocale: string;
|
|
10
|
+
};
|
|
11
|
+
export type GetLocaleOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Makes the locale URL-friendly by replacing underscores with dashes, and converting the locale to lower case.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
normalizeLocale?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* An optional path to add after the `locale`.
|
|
19
|
+
*/
|
|
20
|
+
path?: string;
|
|
21
|
+
/**
|
|
22
|
+
* An optional path to prepend to `locale`.
|
|
23
|
+
*/
|
|
24
|
+
prependWith?: string;
|
|
25
|
+
};
|
|
26
|
+
type GetLocaleAbsoluteUrl = GetLocaleRelativeUrl & {
|
|
27
|
+
site: AstroConfig['site'];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* The base URL
|
|
31
|
+
*/
|
|
32
|
+
export declare function getLocaleRelativeUrl({ locale, base, locales, trailingSlash, format, path, prependWith, normalizeLocale, routingStrategy, defaultLocale, }: GetLocaleRelativeUrl): string;
|
|
33
|
+
/**
|
|
34
|
+
* The absolute URL
|
|
35
|
+
*/
|
|
36
|
+
export declare function getLocaleAbsoluteUrl({ site, ...rest }: GetLocaleAbsoluteUrl): string;
|
|
37
|
+
type GetLocalesBaseUrl = GetLocaleOptions & {
|
|
38
|
+
base: string;
|
|
39
|
+
locales: string[];
|
|
40
|
+
trailingSlash: AstroConfig['trailingSlash'];
|
|
41
|
+
format: AstroConfig['build']['format'];
|
|
42
|
+
routingStrategy?: 'prefix-always' | 'prefix-other-locales';
|
|
43
|
+
defaultLocale: string;
|
|
44
|
+
};
|
|
45
|
+
export declare function getLocaleRelativeUrlList({ base, locales, trailingSlash, format, path, prependWith, normalizeLocale, routingStrategy, defaultLocale, }: GetLocalesBaseUrl): string[];
|
|
46
|
+
export declare function getLocaleAbsoluteUrlList({ site, ...rest }: GetLocaleAbsoluteUrl): string[];
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* Given a locale, this function:
|
|
50
|
+
* - replaces the `_` with a `-`;
|
|
51
|
+
* - transforms all letters to be lower case;
|
|
52
|
+
*/
|
|
53
|
+
export declare function normalizeTheLocale(locale: string): string;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { appendForwardSlash, joinPaths } from "@astrojs/internal-helpers/path";
|
|
2
|
+
import { shouldAppendForwardSlash } from "../core/build/util.js";
|
|
3
|
+
import { MissingLocale } from "../core/errors/errors-data.js";
|
|
4
|
+
import { AstroError } from "../core/errors/index.js";
|
|
5
|
+
function getLocaleRelativeUrl({
|
|
6
|
+
locale,
|
|
7
|
+
base,
|
|
8
|
+
locales,
|
|
9
|
+
trailingSlash,
|
|
10
|
+
format,
|
|
11
|
+
path,
|
|
12
|
+
prependWith,
|
|
13
|
+
normalizeLocale = true,
|
|
14
|
+
routingStrategy = "prefix-other-locales",
|
|
15
|
+
defaultLocale
|
|
16
|
+
}) {
|
|
17
|
+
if (!locales.includes(locale)) {
|
|
18
|
+
throw new AstroError({
|
|
19
|
+
...MissingLocale,
|
|
20
|
+
message: MissingLocale.message(locale, locales)
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const pathsToJoin = [base, prependWith];
|
|
24
|
+
const normalizedLocale = normalizeLocale ? normalizeTheLocale(locale) : locale;
|
|
25
|
+
if (routingStrategy === "prefix-always") {
|
|
26
|
+
pathsToJoin.push(normalizedLocale);
|
|
27
|
+
} else if (locale !== defaultLocale) {
|
|
28
|
+
pathsToJoin.push(normalizedLocale);
|
|
29
|
+
}
|
|
30
|
+
pathsToJoin.push(path);
|
|
31
|
+
if (shouldAppendForwardSlash(trailingSlash, format)) {
|
|
32
|
+
return appendForwardSlash(joinPaths(...pathsToJoin));
|
|
33
|
+
} else {
|
|
34
|
+
return joinPaths(...pathsToJoin);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function getLocaleAbsoluteUrl({ site, ...rest }) {
|
|
38
|
+
const locale = getLocaleRelativeUrl(rest);
|
|
39
|
+
if (site) {
|
|
40
|
+
return joinPaths(site, locale);
|
|
41
|
+
} else {
|
|
42
|
+
return locale;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function getLocaleRelativeUrlList({
|
|
46
|
+
base,
|
|
47
|
+
locales,
|
|
48
|
+
trailingSlash,
|
|
49
|
+
format,
|
|
50
|
+
path,
|
|
51
|
+
prependWith,
|
|
52
|
+
normalizeLocale = false,
|
|
53
|
+
routingStrategy = "prefix-other-locales",
|
|
54
|
+
defaultLocale
|
|
55
|
+
}) {
|
|
56
|
+
return locales.map((locale) => {
|
|
57
|
+
const pathsToJoin = [base, prependWith];
|
|
58
|
+
const normalizedLocale = normalizeLocale ? normalizeTheLocale(locale) : locale;
|
|
59
|
+
if (routingStrategy === "prefix-always") {
|
|
60
|
+
pathsToJoin.push(normalizedLocale);
|
|
61
|
+
} else if (locale !== defaultLocale) {
|
|
62
|
+
pathsToJoin.push(normalizedLocale);
|
|
63
|
+
}
|
|
64
|
+
pathsToJoin.push(path);
|
|
65
|
+
if (shouldAppendForwardSlash(trailingSlash, format)) {
|
|
66
|
+
return appendForwardSlash(joinPaths(...pathsToJoin));
|
|
67
|
+
} else {
|
|
68
|
+
return joinPaths(...pathsToJoin);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function getLocaleAbsoluteUrlList({ site, ...rest }) {
|
|
73
|
+
const locales = getLocaleRelativeUrlList(rest);
|
|
74
|
+
return locales.map((locale) => {
|
|
75
|
+
if (site) {
|
|
76
|
+
return joinPaths(site, locale);
|
|
77
|
+
} else {
|
|
78
|
+
return locale;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function normalizeTheLocale(locale) {
|
|
83
|
+
return locale.replaceAll("_", "-").toLowerCase();
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
getLocaleAbsoluteUrl,
|
|
87
|
+
getLocaleAbsoluteUrlList,
|
|
88
|
+
getLocaleRelativeUrl,
|
|
89
|
+
getLocaleRelativeUrlList,
|
|
90
|
+
normalizeTheLocale
|
|
91
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { joinPaths } from "@astrojs/internal-helpers/path";
|
|
2
|
+
function checkIsLocaleFree(pathname, locales) {
|
|
3
|
+
for (const locale of locales) {
|
|
4
|
+
if (pathname.includes(`/${locale}`)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
function createI18nMiddleware(i18n, base) {
|
|
11
|
+
if (!i18n) {
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
return async (context, next) => {
|
|
15
|
+
if (!i18n) {
|
|
16
|
+
return await next();
|
|
17
|
+
}
|
|
18
|
+
const { locales, defaultLocale, fallback } = i18n;
|
|
19
|
+
const url = context.url;
|
|
20
|
+
const response = await next();
|
|
21
|
+
if (response instanceof Response) {
|
|
22
|
+
const separators = url.pathname.split("/");
|
|
23
|
+
const pathnameContainsDefaultLocale = url.pathname.includes(`/${defaultLocale}`);
|
|
24
|
+
const isLocaleFree = checkIsLocaleFree(url.pathname, i18n.locales);
|
|
25
|
+
if (i18n.routingStrategy === "prefix-other-locales" && pathnameContainsDefaultLocale) {
|
|
26
|
+
const newLocation = url.pathname.replace(`/${defaultLocale}`, "");
|
|
27
|
+
response.headers.set("Location", newLocation);
|
|
28
|
+
return new Response(null, {
|
|
29
|
+
status: 404,
|
|
30
|
+
headers: response.headers
|
|
31
|
+
});
|
|
32
|
+
} else if (i18n.routingStrategy === "prefix-always") {
|
|
33
|
+
if (url.pathname === base || url.pathname === base + "/") {
|
|
34
|
+
return context.redirect(`${joinPaths(base, i18n.defaultLocale)}`);
|
|
35
|
+
} else if (isLocaleFree) {
|
|
36
|
+
return new Response(null, {
|
|
37
|
+
status: 404,
|
|
38
|
+
headers: response.headers
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (response.status >= 300 && fallback) {
|
|
43
|
+
const fallbackKeys = i18n.fallback ? Object.keys(i18n.fallback) : [];
|
|
44
|
+
const urlLocale = separators.find((s) => locales.includes(s));
|
|
45
|
+
if (urlLocale && fallbackKeys.includes(urlLocale)) {
|
|
46
|
+
const fallbackLocale = fallback[urlLocale];
|
|
47
|
+
let newPathname;
|
|
48
|
+
if (fallbackLocale === defaultLocale) {
|
|
49
|
+
newPathname = url.pathname.replace(`/${urlLocale}`, ``);
|
|
50
|
+
} else {
|
|
51
|
+
newPathname = url.pathname.replace(`/${urlLocale}`, `/${fallbackLocale}`);
|
|
52
|
+
}
|
|
53
|
+
return context.redirect(newPathname);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
createI18nMiddleware
|
|
62
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as vite from 'vite';
|
|
2
|
+
import type { AstroSettings } from '../@types/astro.js';
|
|
3
|
+
type AstroInternationalization = {
|
|
4
|
+
settings: AstroSettings;
|
|
5
|
+
};
|
|
6
|
+
export default function astroInternationalization({ settings, }: AstroInternationalization): vite.Plugin;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as vite from "vite";
|
|
2
|
+
const virtualModuleId = "astro:i18n";
|
|
3
|
+
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
4
|
+
function astroInternationalization({
|
|
5
|
+
settings
|
|
6
|
+
}) {
|
|
7
|
+
return {
|
|
8
|
+
name: "astro:i18n",
|
|
9
|
+
enforce: "pre",
|
|
10
|
+
async resolveId(id) {
|
|
11
|
+
if (id === virtualModuleId) {
|
|
12
|
+
return resolvedVirtualModuleId;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
load(id) {
|
|
16
|
+
if (id === resolvedVirtualModuleId) {
|
|
17
|
+
return `
|
|
18
|
+
import {
|
|
19
|
+
getLocaleRelativeUrl as _getLocaleRelativeUrl,
|
|
20
|
+
getLocaleRelativeUrlList as _getLocaleRelativeUrlList,
|
|
21
|
+
getLocaleAbsoluteUrl as _getLocaleAbsoluteUrl,
|
|
22
|
+
getLocaleAbsoluteUrlList as _getLocaleAbsoluteUrlList,
|
|
23
|
+
|
|
24
|
+
} from "astro/i18n";
|
|
25
|
+
|
|
26
|
+
const base = ${JSON.stringify(settings.config.base)};
|
|
27
|
+
const trailingSlash = ${JSON.stringify(settings.config.trailingSlash)};
|
|
28
|
+
const format = ${JSON.stringify(settings.config.build.format)};
|
|
29
|
+
const site = ${JSON.stringify(settings.config.site)};
|
|
30
|
+
const i18n = ${JSON.stringify(settings.config.experimental.i18n)};
|
|
31
|
+
|
|
32
|
+
export const getRelativeLocaleUrl = (locale, path = "", opts) => _getLocaleRelativeUrl({
|
|
33
|
+
locale,
|
|
34
|
+
path,
|
|
35
|
+
base,
|
|
36
|
+
trailingSlash,
|
|
37
|
+
format,
|
|
38
|
+
...i18n,
|
|
39
|
+
...opts
|
|
40
|
+
});
|
|
41
|
+
export const getAbsoluteLocaleUrl = (locale, path = "", opts) => _getLocaleAbsoluteUrl({
|
|
42
|
+
locale,
|
|
43
|
+
path,
|
|
44
|
+
base,
|
|
45
|
+
trailingSlash,
|
|
46
|
+
format,
|
|
47
|
+
site,
|
|
48
|
+
...i18n,
|
|
49
|
+
...opts
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const getRelativeLocaleUrlList = (path = "", opts) => _getLocaleRelativeUrlList({
|
|
53
|
+
base, path, trailingSlash, format, ...i18n, ...opts });
|
|
54
|
+
export const getAbsoluteLocaleUrlList = (path = "", opts) => _getLocaleAbsoluteUrlList({ base, path, trailingSlash, format, site, ...i18n, ...opts });
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
astroInternationalization as default
|
|
62
|
+
};
|
|
@@ -11,7 +11,10 @@ const ALL_UNSUPPORTED = {
|
|
|
11
11
|
serverOutput: UNSUPPORTED,
|
|
12
12
|
staticOutput: UNSUPPORTED,
|
|
13
13
|
hybridOutput: UNSUPPORTED,
|
|
14
|
-
assets: UNSUPPORTED_ASSETS_FEATURE
|
|
14
|
+
assets: UNSUPPORTED_ASSETS_FEATURE,
|
|
15
|
+
i18n: {
|
|
16
|
+
detectBrowserLanguage: UNSUPPORTED
|
|
17
|
+
}
|
|
15
18
|
};
|
|
16
19
|
function validateSupportedFeatures(adapterName, featureMap = ALL_UNSUPPORTED, config, logger) {
|
|
17
20
|
const {
|