astro 6.0.8 → 6.1.1
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 +30 -40
- package/dist/assets/build/generate.js +17 -19
- package/dist/assets/build/remote.d.ts +4 -4
- package/dist/assets/build/remote.js +12 -10
- package/dist/assets/fonts/infra/dev-font-file-id-generator.js +4 -1
- package/dist/assets/fonts/vite-plugin-fonts.js +8 -0
- package/dist/assets/services/sharp.d.ts +21 -2
- package/dist/assets/services/sharp.js +54 -12
- package/dist/assets/vite-plugin-assets.js +4 -1
- package/dist/cli/add/index.js +55 -1
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +2 -3
- package/dist/content/runtime.d.ts +2 -0
- package/dist/content/runtime.js +2 -1
- package/dist/content/types-generator.js +4 -0
- package/dist/content/utils.d.ts +0 -1
- package/dist/content/utils.js +1 -10
- package/dist/core/app/dev/app.d.ts +5 -0
- package/dist/core/app/dev/app.js +7 -0
- package/dist/core/app/entrypoints/virtual/dev.js +4 -0
- package/dist/core/app/node.js +5 -4
- package/dist/core/app/validate-headers.d.ts +6 -0
- package/dist/core/app/validate-headers.js +4 -0
- package/dist/core/base-pipeline.d.ts +5 -0
- package/dist/core/base-pipeline.js +7 -0
- package/dist/core/build/generate.d.ts +47 -0
- package/dist/core/build/generate.js +43 -25
- package/dist/core/build/plugins/plugin-css.js +8 -4
- package/dist/core/config/schemas/base.d.ts +4 -2
- package/dist/core/config/schemas/base.js +22 -1
- package/dist/core/config/schemas/relative.d.ts +3 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +1 -1
- package/dist/core/dev/dev.js +13 -1
- package/dist/core/errors/errors-data.d.ts +2 -2
- package/dist/core/head-propagation/boundary.d.ts +8 -0
- package/dist/core/head-propagation/boundary.js +11 -0
- package/dist/core/head-propagation/buffer.d.ts +21 -0
- package/dist/core/head-propagation/buffer.js +18 -0
- package/dist/core/head-propagation/comment.d.ts +7 -0
- package/dist/core/head-propagation/comment.js +7 -0
- package/dist/core/head-propagation/graph.d.ts +18 -0
- package/dist/core/head-propagation/graph.js +32 -0
- package/dist/core/head-propagation/policy.d.ts +22 -0
- package/dist/core/head-propagation/policy.js +14 -0
- package/dist/core/head-propagation/resolver.d.ts +28 -0
- package/dist/core/head-propagation/resolver.js +25 -0
- package/dist/core/messages/runtime.d.ts +3 -0
- package/dist/core/messages/runtime.js +9 -1
- package/dist/core/middleware/vite-plugin.d.ts +1 -1
- package/dist/core/middleware/vite-plugin.js +25 -0
- package/dist/core/redirects/render.d.ts +17 -0
- package/dist/core/redirects/render.js +33 -24
- package/dist/core/routing/create-manifest.d.ts +15 -0
- package/dist/core/routing/create-manifest.js +131 -130
- package/dist/core/routing/prerender.d.ts +5 -0
- package/dist/core/routing/prerender.js +7 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +18 -6
- package/dist/integrations/hooks.js +4 -1
- package/dist/jsx/rehype.js +1 -1
- package/dist/manifest/serialized.js +5 -0
- package/dist/manifest/virtual-module.d.ts +4 -1
- package/dist/manifest/virtual-module.js +37 -35
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +15 -5
- package/dist/runtime/server/render/astro/factory.js +6 -7
- package/dist/runtime/server/render/astro/instance.js +2 -4
- package/dist/runtime/server/render/astro/render.js +2 -11
- package/dist/runtime/server/render/common.js +3 -2
- package/dist/runtime/server/render/head-propagation/runtime.d.ts +20 -0
- package/dist/runtime/server/render/head-propagation/runtime.js +53 -0
- package/dist/runtime/server/render/page.js +5 -1
- package/dist/runtime/server/transition.d.ts +19 -1
- package/dist/runtime/server/transition.js +6 -1
- package/dist/transitions/events.d.ts +1 -1
- package/dist/transitions/events.js +5 -5
- package/dist/transitions/router.js +23 -19
- package/dist/transitions/swap-functions.js +6 -0
- package/dist/types/public/config.d.ts +71 -12
- package/dist/types/public/integrations.d.ts +9 -2
- package/dist/vite-plugin-app/app.d.ts +5 -0
- package/dist/vite-plugin-app/app.js +17 -1
- package/dist/vite-plugin-app/createAstroServerApp.js +4 -0
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/dist/vite-plugin-astro-server/vite.js +2 -2
- package/dist/vite-plugin-head/index.js +63 -25
- package/dist/vite-plugin-scripts/index.js +5 -0
- package/package.json +11 -11
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { PropagationHint, SSRResult } from '../../types/public/internal.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the effective propagation hint for a component.
|
|
4
|
+
*
|
|
5
|
+
* Priority: explicit factory hint -> component metadata -> `none`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* A runtime-created head entry uses `propagation: 'self'`, so it propagates
|
|
9
|
+
* even when metadata says `none`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolvePropagationHint(input: {
|
|
12
|
+
factoryHint: PropagationHint | undefined;
|
|
13
|
+
moduleId: string | undefined;
|
|
14
|
+
metadataLookup: (moduleId: string) => PropagationHint | undefined;
|
|
15
|
+
}): PropagationHint;
|
|
16
|
+
/** Returns true when a hint should register a component as a propagator. */
|
|
17
|
+
export declare function isPropagatingHint(hint: PropagationHint): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Reads propagation metadata from an `SSRResult` + component factory.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* A compiled `.astro` module with metadata `in-tree` is treated as propagating
|
|
23
|
+
* when the factory does not set a stronger explicit hint.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getPropagationHint(result: SSRResult, factory: {
|
|
26
|
+
propagation?: PropagationHint;
|
|
27
|
+
moduleId?: string | undefined;
|
|
28
|
+
}): PropagationHint;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function resolvePropagationHint(input) {
|
|
2
|
+
const explicitHint = input.factoryHint ?? "none";
|
|
3
|
+
if (explicitHint !== "none") {
|
|
4
|
+
return explicitHint;
|
|
5
|
+
}
|
|
6
|
+
if (!input.moduleId) {
|
|
7
|
+
return "none";
|
|
8
|
+
}
|
|
9
|
+
return input.metadataLookup(input.moduleId) ?? "none";
|
|
10
|
+
}
|
|
11
|
+
function isPropagatingHint(hint) {
|
|
12
|
+
return hint === "self" || hint === "in-tree";
|
|
13
|
+
}
|
|
14
|
+
function getPropagationHint(result, factory) {
|
|
15
|
+
return resolvePropagationHint({
|
|
16
|
+
factoryHint: factory.propagation,
|
|
17
|
+
moduleId: factory.moduleId,
|
|
18
|
+
metadataLookup: (moduleId) => result.componentMetadata.get(moduleId)?.propagation
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
getPropagationHint,
|
|
23
|
+
isPropagatingHint,
|
|
24
|
+
resolvePropagationHint
|
|
25
|
+
};
|
|
@@ -41,6 +41,9 @@ export declare function preferenceReset(name: string): string;
|
|
|
41
41
|
export declare function telemetryDisabled(): string;
|
|
42
42
|
export declare function telemetryReset(): string;
|
|
43
43
|
export declare function fsStrictWarning(): string;
|
|
44
|
+
export declare function vite8Warning({ viteVersion }: {
|
|
45
|
+
viteVersion: string;
|
|
46
|
+
}): string;
|
|
44
47
|
export declare function prerelease({ currentVersion }: {
|
|
45
48
|
currentVersion: string;
|
|
46
49
|
}): string;
|
|
@@ -134,6 +134,13 @@ function fsStrictWarning() {
|
|
|
134
134
|
${subtitle}
|
|
135
135
|
`;
|
|
136
136
|
}
|
|
137
|
+
function vite8Warning({ viteVersion }) {
|
|
138
|
+
const title = yellow(`\u25B6 Vite ${bold(viteVersion)} detected in your project.`);
|
|
139
|
+
const subtitle = ` Astro requires Vite 7. Add ${bold('"overrides": { "vite": "^7" }')} to your ${bold("package.json")} to avoid issues.`;
|
|
140
|
+
return `${title}
|
|
141
|
+
${subtitle}
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
137
144
|
function prerelease({ currentVersion }) {
|
|
138
145
|
const tag = currentVersion.split("-").slice(1).join("-").replace(/\..*$/, "") || "unknown";
|
|
139
146
|
const badge = bgYellow(black(` ${tag} `));
|
|
@@ -269,7 +276,7 @@ function printHelp({
|
|
|
269
276
|
message.push(
|
|
270
277
|
linebreak(),
|
|
271
278
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
272
|
-
`v${"6.
|
|
279
|
+
`v${"6.1.1"}`
|
|
273
280
|
)} ${headline}`
|
|
274
281
|
);
|
|
275
282
|
}
|
|
@@ -327,5 +334,6 @@ export {
|
|
|
327
334
|
telemetryEnabled,
|
|
328
335
|
telemetryNotice,
|
|
329
336
|
telemetryReset,
|
|
337
|
+
vite8Warning,
|
|
330
338
|
warnIfCspWithShiki
|
|
331
339
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Plugin as VitePlugin } from 'vite';
|
|
2
2
|
import type { AstroSettings } from '../../types/astro.js';
|
|
3
3
|
import type { BuildInternals } from '../build/internal.js';
|
|
4
4
|
import type { StaticBuildOptions } from '../build/types.js';
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import {
|
|
3
|
+
normalizePath as viteNormalizePath
|
|
4
|
+
} from "vite";
|
|
1
5
|
import { getServerOutputDirectory } from "../../prerender/utils.js";
|
|
2
6
|
import { addRollupInput } from "../build/add-rollup-input.js";
|
|
3
7
|
import { ASTRO_VITE_ENVIRONMENT_NAMES, MIDDLEWARE_PATH_SEGMENT_NAME } from "../constants.js";
|
|
@@ -11,11 +15,32 @@ function vitePluginMiddleware({ settings }) {
|
|
|
11
15
|
let resolvedMiddlewareId = void 0;
|
|
12
16
|
const hasIntegrationMiddleware = settings.middlewares.pre.length > 0 || settings.middlewares.post.length > 0;
|
|
13
17
|
let userMiddlewareIsPresent = false;
|
|
18
|
+
const normalizedSrcDir = viteNormalizePath(fileURLToPath(settings.config.srcDir));
|
|
14
19
|
return {
|
|
15
20
|
name: "@astro/plugin-middleware",
|
|
16
21
|
applyToEnvironment(environment) {
|
|
17
22
|
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.astro || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
|
|
18
23
|
},
|
|
24
|
+
configureServer(server) {
|
|
25
|
+
server.watcher.on("change", (path) => {
|
|
26
|
+
const normalizedPath = viteNormalizePath(path);
|
|
27
|
+
if (!normalizedPath.startsWith(normalizedSrcDir)) return;
|
|
28
|
+
const relativePath = normalizedPath.slice(normalizedSrcDir.length);
|
|
29
|
+
if (!relativePath.startsWith(`${MIDDLEWARE_PATH_SEGMENT_NAME}.`)) return;
|
|
30
|
+
for (const name of [
|
|
31
|
+
ASTRO_VITE_ENVIRONMENT_NAMES.ssr,
|
|
32
|
+
ASTRO_VITE_ENVIRONMENT_NAMES.astro
|
|
33
|
+
]) {
|
|
34
|
+
const environment = server.environments[name];
|
|
35
|
+
if (!environment) continue;
|
|
36
|
+
const virtualMod = environment.moduleGraph.getModuleById(MIDDLEWARE_RESOLVED_MODULE_ID);
|
|
37
|
+
if (virtualMod) {
|
|
38
|
+
environment.moduleGraph.invalidateModule(virtualMod);
|
|
39
|
+
}
|
|
40
|
+
environment.hot.send("astro:middleware-updated", {});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
},
|
|
19
44
|
resolveId: {
|
|
20
45
|
filter: {
|
|
21
46
|
id: new RegExp(`^${MIDDLEWARE_MODULE_ID}$`)
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
import type { Params } from '../../types/public/common.js';
|
|
1
2
|
import type { RedirectConfig } from '../../types/public/index.js';
|
|
3
|
+
import type { RouteData } from '../../types/public/internal.js';
|
|
2
4
|
import type { RenderContext } from '../render-context.js';
|
|
3
5
|
export declare function redirectIsExternal(redirect: RedirectConfig): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Computes the HTTP status code for a redirect response.
|
|
8
|
+
*
|
|
9
|
+
* - If the route has a `redirectRoute` and an explicit numeric status, that status is used.
|
|
10
|
+
* - Otherwise: GET → 301, non-GET (e.g. POST) → 308.
|
|
11
|
+
*/
|
|
12
|
+
export declare function computeRedirectStatus(method: string, redirect: RedirectConfig | undefined, redirectRoute: RouteData | undefined): number;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the final redirect target URL by substituting dynamic params into
|
|
15
|
+
* the redirect string (e.g. `/[slug]/page` → `/hello/page`).
|
|
16
|
+
*
|
|
17
|
+
* When `redirectRoute` is provided its route generator is used; otherwise params
|
|
18
|
+
* are substituted manually into the string redirect target.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveRedirectTarget(params: Params, redirect: RedirectConfig | undefined, redirectRoute: RouteData | undefined, trailingSlash: 'always' | 'never' | 'ignore'): string;
|
|
4
21
|
export declare function renderRedirect(renderContext: RenderContext): Promise<Response>;
|
|
@@ -9,31 +9,12 @@ function redirectIsExternal(redirect) {
|
|
|
9
9
|
return isExternalURL(redirect.destination);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
request: { method },
|
|
15
|
-
routeData
|
|
16
|
-
} = renderContext;
|
|
17
|
-
const { redirect, redirectRoute } = routeData;
|
|
18
|
-
const status = redirectRoute && typeof redirect === "object" ? redirect.status : method === "GET" ? 301 : 308;
|
|
19
|
-
const headers = { location: encodeURI(redirectRouteGenerate(renderContext)) };
|
|
20
|
-
if (redirect && redirectIsExternal(redirect)) {
|
|
21
|
-
if (typeof redirect === "string") {
|
|
22
|
-
return Response.redirect(redirect, status);
|
|
23
|
-
} else {
|
|
24
|
-
return Response.redirect(redirect.destination, status);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return new Response(null, { status, headers });
|
|
12
|
+
function computeRedirectStatus(method, redirect, redirectRoute) {
|
|
13
|
+
return redirectRoute && typeof redirect === "object" ? redirect.status : method === "GET" ? 301 : 308;
|
|
28
14
|
}
|
|
29
|
-
function
|
|
30
|
-
const {
|
|
31
|
-
params,
|
|
32
|
-
routeData: { redirect, redirectRoute },
|
|
33
|
-
pipeline
|
|
34
|
-
} = renderContext;
|
|
15
|
+
function resolveRedirectTarget(params, redirect, redirectRoute, trailingSlash) {
|
|
35
16
|
if (typeof redirectRoute !== "undefined") {
|
|
36
|
-
const generate = getRouteGenerator(redirectRoute.segments,
|
|
17
|
+
const generate = getRouteGenerator(redirectRoute.segments, trailingSlash);
|
|
37
18
|
return generate(params) || redirectRoute?.pathname || "/";
|
|
38
19
|
} else if (typeof redirect === "string") {
|
|
39
20
|
if (redirectIsExternal(redirect)) {
|
|
@@ -51,7 +32,35 @@ function redirectRouteGenerate(renderContext) {
|
|
|
51
32
|
}
|
|
52
33
|
return redirect.destination;
|
|
53
34
|
}
|
|
35
|
+
async function renderRedirect(renderContext) {
|
|
36
|
+
const {
|
|
37
|
+
request: { method },
|
|
38
|
+
routeData
|
|
39
|
+
} = renderContext;
|
|
40
|
+
const { redirect, redirectRoute } = routeData;
|
|
41
|
+
const status = computeRedirectStatus(method, redirect, redirectRoute);
|
|
42
|
+
const headers = {
|
|
43
|
+
location: encodeURI(
|
|
44
|
+
resolveRedirectTarget(
|
|
45
|
+
renderContext.params,
|
|
46
|
+
redirect,
|
|
47
|
+
redirectRoute,
|
|
48
|
+
renderContext.pipeline.manifest.trailingSlash
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
};
|
|
52
|
+
if (redirect && redirectIsExternal(redirect)) {
|
|
53
|
+
if (typeof redirect === "string") {
|
|
54
|
+
return Response.redirect(redirect, status);
|
|
55
|
+
} else {
|
|
56
|
+
return Response.redirect(redirect.destination, status);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return new Response(null, { status, headers });
|
|
60
|
+
}
|
|
54
61
|
export {
|
|
62
|
+
computeRedirectStatus,
|
|
55
63
|
redirectIsExternal,
|
|
56
|
-
renderRedirect
|
|
64
|
+
renderRedirect,
|
|
65
|
+
resolveRedirectTarget
|
|
57
66
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import nodeFs from 'node:fs';
|
|
2
2
|
import type { AstroSettings, RoutesList } from '../../types/astro.js';
|
|
3
|
+
import type { AstroConfig } from '../../types/public/config.js';
|
|
3
4
|
import type { RouteData } from '../../types/public/internal.js';
|
|
4
5
|
import type { Logger } from '../logger/core.js';
|
|
5
6
|
export interface RouteEntry {
|
|
@@ -22,6 +23,20 @@ export declare function createRoutesFromEntries(entries: RouteEntry[], settings:
|
|
|
22
23
|
export declare function createRoutesList(params: CreateRouteManifestParams, logger: Logger, { dev, }?: {
|
|
23
24
|
dev?: boolean;
|
|
24
25
|
}): Promise<RoutesList>;
|
|
26
|
+
/**
|
|
27
|
+
* Generates i18n fallback routes and attaches them to their source routes.
|
|
28
|
+
*
|
|
29
|
+
* For each locale that has a fallback configured (e.g. `{ es: 'en' }`), this
|
|
30
|
+
* function inspects the existing route list and creates `type: 'fallback'`
|
|
31
|
+
* entries for any paths that the source locale does not already have. The
|
|
32
|
+
* fallback routes are pushed onto `route.fallbackRoutes` of their source route
|
|
33
|
+
* so that the build pipeline can serve the fallback content.
|
|
34
|
+
*
|
|
35
|
+
* @param routes The full route list — mutated in-place.
|
|
36
|
+
* @param i18n The resolved `config.i18n` object.
|
|
37
|
+
* @param config The resolved Astro config (needs `base` and `trailingSlash`).
|
|
38
|
+
*/
|
|
39
|
+
export declare function createI18nFallbackRoutes(routes: RouteData[], i18n: NonNullable<AstroConfig['i18n']>, config: Pick<AstroConfig, 'base' | 'trailingSlash'>): void;
|
|
25
40
|
/**
|
|
26
41
|
* Resolve a route entrypoint to an absolute component path.
|
|
27
42
|
*/
|
|
@@ -63,6 +63,7 @@ function createFileBasedRoutes({ settings, cwd, fsMod }, logger) {
|
|
|
63
63
|
const pages = resolvePages(config);
|
|
64
64
|
const localFs = fsMod ?? nodeFs;
|
|
65
65
|
const rootPath = fileURLToPath(config.root);
|
|
66
|
+
const pagesPath = fileURLToPath(pages);
|
|
66
67
|
if (!localFs.existsSync(pages)) {
|
|
67
68
|
if (settings.injectedRoutes.length === 0) {
|
|
68
69
|
const pagesDirRootRelative = pages.href.slice(settings.config.root.href.length);
|
|
@@ -177,7 +178,7 @@ function createFileBasedRoutes({ settings, cwd, fsMod }, logger) {
|
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
|
-
walk(localFs,
|
|
181
|
+
walk(localFs, pagesPath, [], []);
|
|
181
182
|
return routes;
|
|
182
183
|
}
|
|
183
184
|
function createRoutesFromEntries(entries, settings, logger, pagesDirRelative = "src/pages") {
|
|
@@ -467,16 +468,12 @@ async function createRoutesList(params, logger, {
|
|
|
467
468
|
if (route.type !== "page" && route.type !== "endpoint" && route.type !== "redirect") return;
|
|
468
469
|
if (route.type === "redirect" && !route.redirectRoute) return;
|
|
469
470
|
const localFs = params.fsMod ?? nodeFs;
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
route.type === "redirect" && route.redirectRoute ? route.redirectRoute.component : route.component,
|
|
475
|
-
settings.config.root
|
|
476
|
-
)
|
|
477
|
-
),
|
|
478
|
-
"utf-8"
|
|
471
|
+
const componentUrl = new URL(
|
|
472
|
+
// The destination redirect might be a prerendered
|
|
473
|
+
route.type === "redirect" && route.redirectRoute ? route.redirectRoute.component : route.component,
|
|
474
|
+
settings.config.root
|
|
479
475
|
);
|
|
476
|
+
const content = await localFs.promises.readFile(componentUrl, "utf-8");
|
|
480
477
|
await getRoutePrerenderOption(content, route, settings, logger);
|
|
481
478
|
})
|
|
482
479
|
);
|
|
@@ -504,144 +501,147 @@ async function createRoutesList(params, logger, {
|
|
|
504
501
|
});
|
|
505
502
|
}
|
|
506
503
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
} else {
|
|
531
|
-
routesByLocale.set(locale, [route]);
|
|
532
|
-
}
|
|
533
|
-
setRoutes.delete(route);
|
|
534
|
-
}
|
|
504
|
+
createI18nFallbackRoutes(routes, i18n, config);
|
|
505
|
+
}
|
|
506
|
+
if (dev) {
|
|
507
|
+
ensure404Route({ routes });
|
|
508
|
+
}
|
|
509
|
+
if (dev || settings.buildOutput === "server") {
|
|
510
|
+
injectImageEndpoint(settings, { routes }, dev ? "dev" : "build");
|
|
511
|
+
}
|
|
512
|
+
if (dev || settings.config.adapter) {
|
|
513
|
+
injectServerIslandRoute(settings.config, { routes });
|
|
514
|
+
}
|
|
515
|
+
await runHookRoutesResolved({ routes, settings, logger });
|
|
516
|
+
return {
|
|
517
|
+
routes
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function createI18nFallbackRoutes(routes, i18n, config) {
|
|
521
|
+
const strategy = toRoutingStrategy(i18n.routing, i18n.domains);
|
|
522
|
+
const routesByLocale = /* @__PURE__ */ new Map();
|
|
523
|
+
const setRoutes = new Set(routes.filter((route) => route.type === "page"));
|
|
524
|
+
const filteredLocales = i18n.locales.filter((loc) => {
|
|
525
|
+
if (typeof loc === "string") {
|
|
526
|
+
return loc !== i18n.defaultLocale;
|
|
535
527
|
}
|
|
528
|
+
return loc.path !== i18n.defaultLocale;
|
|
529
|
+
}).map((locale) => {
|
|
530
|
+
if (typeof locale === "string") {
|
|
531
|
+
return locale;
|
|
532
|
+
}
|
|
533
|
+
return locale.path;
|
|
534
|
+
});
|
|
535
|
+
for (const locale of filteredLocales) {
|
|
536
536
|
for (const route of setRoutes) {
|
|
537
|
-
const
|
|
537
|
+
const hasLocaleInRoute = route.route.split("/").includes(locale);
|
|
538
|
+
if (!hasLocaleInRoute) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
const currentRoutes = routesByLocale.get(locale);
|
|
538
542
|
if (currentRoutes) {
|
|
539
543
|
currentRoutes.push(route);
|
|
540
|
-
routesByLocale.set(
|
|
544
|
+
routesByLocale.set(locale, currentRoutes);
|
|
541
545
|
} else {
|
|
542
|
-
routesByLocale.set(
|
|
546
|
+
routesByLocale.set(locale, [route]);
|
|
543
547
|
}
|
|
544
548
|
setRoutes.delete(route);
|
|
545
549
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
550
|
+
}
|
|
551
|
+
for (const route of setRoutes) {
|
|
552
|
+
const currentRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
553
|
+
if (currentRoutes) {
|
|
554
|
+
currentRoutes.push(route);
|
|
555
|
+
routesByLocale.set(i18n.defaultLocale, currentRoutes);
|
|
556
|
+
} else {
|
|
557
|
+
routesByLocale.set(i18n.defaultLocale, [route]);
|
|
558
|
+
}
|
|
559
|
+
setRoutes.delete(route);
|
|
560
|
+
}
|
|
561
|
+
if (strategy === "pathname-prefix-always") {
|
|
562
|
+
const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
563
|
+
if (defaultLocaleRoutes) {
|
|
564
|
+
const indexDefaultRoute = defaultLocaleRoutes.find(({ route }) => route === "/") ?? defaultLocaleRoutes.find(({ route }) => route === `/${i18n.defaultLocale}`);
|
|
565
|
+
if (indexDefaultRoute) {
|
|
566
|
+
const pathname = "/";
|
|
567
|
+
const route = "/";
|
|
568
|
+
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
|
569
|
+
validateSegment(s);
|
|
570
|
+
return getParts(s, route);
|
|
571
|
+
});
|
|
572
|
+
routes.push({
|
|
573
|
+
...indexDefaultRoute,
|
|
574
|
+
pathname,
|
|
575
|
+
route,
|
|
576
|
+
segments,
|
|
577
|
+
pattern: getPattern(segments, config.base, config.trailingSlash),
|
|
578
|
+
type: "fallback"
|
|
579
|
+
});
|
|
566
580
|
}
|
|
567
581
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
582
|
+
}
|
|
583
|
+
if (i18n.fallback) {
|
|
584
|
+
const fallback = Object.entries(i18n.fallback);
|
|
585
|
+
if (fallback.length > 0) {
|
|
586
|
+
for (const [fallbackFromLocale, fallbackToLocale] of fallback) {
|
|
587
|
+
let fallbackToRoutes;
|
|
588
|
+
if (fallbackToLocale === i18n.defaultLocale) {
|
|
589
|
+
fallbackToRoutes = routesByLocale.get(i18n.defaultLocale);
|
|
590
|
+
} else {
|
|
591
|
+
fallbackToRoutes = routesByLocale.get(fallbackToLocale);
|
|
592
|
+
}
|
|
593
|
+
const fallbackFromRoutes = routesByLocale.get(fallbackFromLocale);
|
|
594
|
+
if (!fallbackToRoutes) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
for (const fallbackToRoute of fallbackToRoutes) {
|
|
598
|
+
const hasRoute = fallbackFromRoutes && fallbackFromRoutes.some((route) => {
|
|
599
|
+
if (fallbackToLocale === i18n.defaultLocale) {
|
|
600
|
+
return route.route === `/${fallbackFromLocale}${fallbackToRoute.route}` || route.route.replace(`/${fallbackFromLocale}`, "") === fallbackToRoute.route;
|
|
601
|
+
} else {
|
|
602
|
+
const expectedRoute = replaceOrKeep(
|
|
603
|
+
fallbackToRoute.route,
|
|
604
|
+
fallbackToLocale,
|
|
605
|
+
fallbackFromLocale
|
|
606
|
+
);
|
|
607
|
+
return route.route === expectedRoute;
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
if (!hasRoute) {
|
|
611
|
+
let pathname;
|
|
612
|
+
let route;
|
|
613
|
+
if (fallbackToLocale === i18n.defaultLocale && strategy === "pathname-prefix-other-locales") {
|
|
614
|
+
if (fallbackToRoute.pathname) {
|
|
615
|
+
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
|
|
594
616
|
}
|
|
617
|
+
route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
|
|
618
|
+
} else {
|
|
619
|
+
pathname = fallbackToRoute.pathname ? replaceOrKeep(fallbackToRoute.pathname, fallbackToLocale, fallbackFromLocale) : void 0;
|
|
620
|
+
route = replaceOrKeep(fallbackToRoute.route, fallbackToLocale, fallbackFromLocale);
|
|
621
|
+
}
|
|
622
|
+
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
|
623
|
+
validateSegment(s);
|
|
624
|
+
return getParts(s, route);
|
|
595
625
|
});
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
validateSegment(s);
|
|
610
|
-
return getParts(s, route);
|
|
611
|
-
});
|
|
612
|
-
const index = routes.findIndex((r) => r === fallbackToRoute);
|
|
613
|
-
if (index >= 0) {
|
|
614
|
-
const fallbackRoute = {
|
|
615
|
-
...fallbackToRoute,
|
|
616
|
-
pathname,
|
|
617
|
-
route,
|
|
618
|
-
segments,
|
|
619
|
-
pattern: getPattern(segments, config.base, config.trailingSlash),
|
|
620
|
-
type: "fallback",
|
|
621
|
-
fallbackRoutes: []
|
|
622
|
-
};
|
|
623
|
-
const routeData = routes[index];
|
|
624
|
-
routeData.fallbackRoutes.push(fallbackRoute);
|
|
625
|
-
}
|
|
626
|
+
const index = routes.findIndex((r) => r === fallbackToRoute);
|
|
627
|
+
if (index >= 0) {
|
|
628
|
+
const fallbackRoute = {
|
|
629
|
+
...fallbackToRoute,
|
|
630
|
+
pathname,
|
|
631
|
+
route,
|
|
632
|
+
segments,
|
|
633
|
+
pattern: getPattern(segments, config.base, config.trailingSlash),
|
|
634
|
+
type: "fallback",
|
|
635
|
+
fallbackRoutes: []
|
|
636
|
+
};
|
|
637
|
+
const routeData = routes[index];
|
|
638
|
+
routeData.fallbackRoutes.push(fallbackRoute);
|
|
626
639
|
}
|
|
627
640
|
}
|
|
628
641
|
}
|
|
629
642
|
}
|
|
630
643
|
}
|
|
631
644
|
}
|
|
632
|
-
if (dev) {
|
|
633
|
-
ensure404Route({ routes });
|
|
634
|
-
}
|
|
635
|
-
if (dev || settings.buildOutput === "server") {
|
|
636
|
-
injectImageEndpoint(settings, { routes }, dev ? "dev" : "build");
|
|
637
|
-
}
|
|
638
|
-
if (dev || settings.config.adapter) {
|
|
639
|
-
injectServerIslandRoute(settings.config, { routes });
|
|
640
|
-
}
|
|
641
|
-
await runHookRoutesResolved({ routes, settings, logger });
|
|
642
|
-
return {
|
|
643
|
-
routes
|
|
644
|
-
};
|
|
645
645
|
}
|
|
646
646
|
function resolveInjectedRoute(entrypoint, root, cwd) {
|
|
647
647
|
let resolved;
|
|
@@ -666,6 +666,7 @@ function replaceOrKeep(original, from, to) {
|
|
|
666
666
|
return original.replace(`/${from}/`, `/${to}/`).replace(`/${from}`, `/${to}`);
|
|
667
667
|
}
|
|
668
668
|
export {
|
|
669
|
+
createI18nFallbackRoutes,
|
|
669
670
|
createRoutesFromEntries,
|
|
670
671
|
createRoutesList,
|
|
671
672
|
resolveInjectedRoute
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { AstroSettings } from '../../types/astro.js';
|
|
2
2
|
import type { RouteData } from '../../types/public/internal.js';
|
|
3
3
|
import type { Logger } from '../logger/core.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parses the `export const prerender = true|false` declaration from a route's
|
|
6
|
+
* source content. Returns `true`, `false`, or `undefined` if not present.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parsePrerenderExport(content: string): boolean | undefined;
|
|
4
9
|
export declare function getRoutePrerenderOption(content: string, route: RouteData, settings: AstroSettings, logger: Logger): Promise<void>;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { runHookRouteSetup } from "../../integrations/hooks.js";
|
|
2
2
|
import { getPrerenderDefault } from "../../prerender/utils.js";
|
|
3
3
|
const PRERENDER_REGEX = /^\s*export\s+const\s+prerender\s*=\s*(true|false);?/m;
|
|
4
|
+
function parsePrerenderExport(content) {
|
|
5
|
+
const match = PRERENDER_REGEX.exec(content);
|
|
6
|
+
if (!match) return void 0;
|
|
7
|
+
return match[1] === "true";
|
|
8
|
+
}
|
|
4
9
|
async function getRoutePrerenderOption(content, route, settings, logger) {
|
|
5
10
|
const match = PRERENDER_REGEX.exec(content);
|
|
6
11
|
if (match) {
|
|
@@ -16,5 +21,6 @@ async function getRoutePrerenderOption(content, route, settings, logger) {
|
|
|
16
21
|
if (!route.prerender) settings.buildOutput = "server";
|
|
17
22
|
}
|
|
18
23
|
export {
|
|
19
|
-
getRoutePrerenderOption
|
|
24
|
+
getRoutePrerenderOption,
|
|
25
|
+
parsePrerenderExport
|
|
20
26
|
};
|
|
@@ -12,7 +12,7 @@ function vitePluginServerIslands({
|
|
|
12
12
|
serverIslandsState
|
|
13
13
|
}) {
|
|
14
14
|
let command = "serve";
|
|
15
|
-
let
|
|
15
|
+
let serverEnvironments = [];
|
|
16
16
|
function ensureServerIslandReferenceIds(ctx) {
|
|
17
17
|
for (const [resolvedPath, island] of serverIslandsState.getDiscoveredIslandEntries()) {
|
|
18
18
|
if (serverIslandsState.hasReferenceId(resolvedPath)) continue;
|
|
@@ -38,7 +38,17 @@ function vitePluginServerIslands({
|
|
|
38
38
|
ensureServerIslandReferenceIds(this);
|
|
39
39
|
},
|
|
40
40
|
configureServer(server) {
|
|
41
|
-
|
|
41
|
+
serverEnvironments = [];
|
|
42
|
+
for (const name of [
|
|
43
|
+
ASTRO_VITE_ENVIRONMENT_NAMES.ssr,
|
|
44
|
+
ASTRO_VITE_ENVIRONMENT_NAMES.prerender,
|
|
45
|
+
ASTRO_VITE_ENVIRONMENT_NAMES.astro
|
|
46
|
+
]) {
|
|
47
|
+
const env = server.environments[name];
|
|
48
|
+
if (env) {
|
|
49
|
+
serverEnvironments.push(env);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
42
52
|
},
|
|
43
53
|
resolveId: {
|
|
44
54
|
filter: {
|
|
@@ -92,10 +102,12 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
92
102
|
}
|
|
93
103
|
}
|
|
94
104
|
}
|
|
95
|
-
if (serverIslandsState.hasIslands()
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
if (serverIslandsState.hasIslands()) {
|
|
106
|
+
for (const env of serverEnvironments) {
|
|
107
|
+
const mod = env.moduleGraph.getModuleById(RESOLVED_SERVER_ISLAND_MANIFEST);
|
|
108
|
+
if (mod) {
|
|
109
|
+
env.moduleGraph.invalidateModule(mod);
|
|
110
|
+
}
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
if (id === RESOLVED_SERVER_ISLAND_MANIFEST) {
|