astro 6.4.1 → 6.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/fonts/core/optimize-fallbacks.js +38 -13
- package/dist/assets/fonts/definitions.d.ts +2 -2
- package/dist/assets/fonts/infra/system-fallbacks-provider.d.ts +2 -2
- package/dist/assets/fonts/infra/system-fallbacks-provider.js +46 -9
- package/dist/assets/fonts/types.d.ts +1 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/core/app/base.js +4 -0
- package/dist/core/base-pipeline.d.ts +10 -0
- package/dist/core/base-pipeline.js +11 -0
- package/dist/core/config/validate.js +12 -5
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/fetch/fetch-state.js +12 -9
- package/dist/core/i18n/handler.js +3 -0
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/middleware/astro-middleware.js +0 -4
- package/dist/core/routing/handler.js +2 -1
- package/dist/core/routing/router.d.ts +8 -0
- package/dist/core/routing/router.js +28 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +9 -0
- package/dist/virtual-modules/i18n.d.ts +2 -2
- package/package.json +2 -2
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { isGenericFontFamily, unifontFontFaceDataToProperties } from "../utils.js";
|
|
2
|
+
function deriveFallbackVariant(data) {
|
|
3
|
+
const weight = data.weight;
|
|
4
|
+
if (typeof weight === "number" && weight >= 700) {
|
|
5
|
+
return "bold";
|
|
6
|
+
}
|
|
7
|
+
if (typeof weight === "string") {
|
|
8
|
+
if (weight === "bold") return "bold";
|
|
9
|
+
if (weight.includes(" ")) return "normal";
|
|
10
|
+
const n = Number.parseInt(weight, 10);
|
|
11
|
+
if (!Number.isNaN(n) && n >= 700) return "bold";
|
|
12
|
+
}
|
|
13
|
+
return "normal";
|
|
14
|
+
}
|
|
2
15
|
async function optimizeFallbacks({
|
|
3
16
|
family,
|
|
4
17
|
fallbacks: _fallbacks,
|
|
@@ -14,28 +27,40 @@ async function optimizeFallbacks({
|
|
|
14
27
|
if (!isGenericFontFamily(lastFallback)) {
|
|
15
28
|
return null;
|
|
16
29
|
}
|
|
17
|
-
const
|
|
18
|
-
|
|
30
|
+
const collectedWithLocalFonts = collectedFonts.map((collected) => ({
|
|
31
|
+
collected,
|
|
32
|
+
localFonts: systemFallbacksProvider.getLocalFonts(lastFallback, deriveFallbackVariant(collected.data)) ?? []
|
|
33
|
+
}));
|
|
34
|
+
const uniqueLocalFonts = [];
|
|
35
|
+
for (const { localFonts } of collectedWithLocalFonts) {
|
|
36
|
+
for (const font of localFonts) {
|
|
37
|
+
if (!uniqueLocalFonts.includes(font)) {
|
|
38
|
+
uniqueLocalFonts.push(font);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (uniqueLocalFonts.length === 0) {
|
|
19
43
|
return null;
|
|
20
44
|
}
|
|
21
|
-
if (
|
|
45
|
+
if (uniqueLocalFonts.includes(family.name)) {
|
|
22
46
|
return null;
|
|
23
47
|
}
|
|
24
|
-
const
|
|
25
|
-
font,
|
|
48
|
+
const nameForFont = (font) => (
|
|
26
49
|
// We mustn't wrap in quote because that's handled by the CSS renderer
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
fallbacks = [...
|
|
50
|
+
`${family.uniqueName} fallback: ${font}`
|
|
51
|
+
);
|
|
52
|
+
fallbacks = [...uniqueLocalFonts.map(nameForFont), ...fallbacks];
|
|
30
53
|
let css = "";
|
|
31
|
-
for (const {
|
|
32
|
-
|
|
54
|
+
for (const { collected, localFonts } of collectedWithLocalFonts) {
|
|
55
|
+
const properties = unifontFontFaceDataToProperties(collected.data);
|
|
56
|
+
const metrics = await fontMetricsResolver.getMetrics(family.name, collected);
|
|
57
|
+
for (const font of localFonts) {
|
|
33
58
|
css += fontMetricsResolver.generateFontFace({
|
|
34
|
-
metrics
|
|
59
|
+
metrics,
|
|
35
60
|
fallbackMetrics: systemFallbacksProvider.getMetricsForLocalFont(font),
|
|
36
61
|
font,
|
|
37
|
-
name,
|
|
38
|
-
properties
|
|
62
|
+
name: nameForFont(font),
|
|
63
|
+
properties
|
|
39
64
|
});
|
|
40
65
|
}
|
|
41
66
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as unifont from 'unifont';
|
|
2
2
|
import type { CollectedFontForMetrics } from './core/optimize-fallbacks.js';
|
|
3
|
-
import type { CssProperties, FontFaceMetrics, FontFileData, FontProvider, FontType, GenericFallbackName, ResolveFontOptions, Style } from './types.js';
|
|
3
|
+
import type { CssProperties, FallbackVariant, FontFaceMetrics, FontFileData, FontProvider, FontType, GenericFallbackName, ResolveFontOptions, Style } from './types.js';
|
|
4
4
|
export interface Hasher {
|
|
5
5
|
hashString: (input: string) => string;
|
|
6
6
|
hashObject: (input: Record<string, any>) => string;
|
|
@@ -28,7 +28,7 @@ export interface FontMetricsResolver {
|
|
|
28
28
|
}) => string;
|
|
29
29
|
}
|
|
30
30
|
export interface SystemFallbacksProvider {
|
|
31
|
-
getLocalFonts: (fallback: GenericFallbackName) => Array<string> | null;
|
|
31
|
+
getLocalFonts: (fallback: GenericFallbackName, variant: FallbackVariant) => Array<string> | null;
|
|
32
32
|
getMetricsForLocalFont: (family: string) => FontFaceMetrics;
|
|
33
33
|
}
|
|
34
34
|
export interface FontFetcher {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SystemFallbacksProvider } from '../definitions.js';
|
|
2
|
-
import type { FontFaceMetrics, GenericFallbackName } from '../types.js';
|
|
2
|
+
import type { FallbackVariant, FontFaceMetrics, GenericFallbackName } from '../types.js';
|
|
3
3
|
export declare class RealSystemFallbacksProvider implements SystemFallbacksProvider {
|
|
4
|
-
getLocalFonts(fallback: GenericFallbackName): Array<string> | null;
|
|
4
|
+
getLocalFonts(fallback: GenericFallbackName, variant: FallbackVariant): Array<string> | null;
|
|
5
5
|
getMetricsForLocalFont(family: string): FontFaceMetrics;
|
|
6
6
|
}
|
|
@@ -6,6 +6,14 @@ const SYSTEM_METRICS = {
|
|
|
6
6
|
unitsPerEm: 2048,
|
|
7
7
|
xWidthAvg: 832
|
|
8
8
|
},
|
|
9
|
+
"Times New Roman Bold": {
|
|
10
|
+
ascent: 1825,
|
|
11
|
+
descent: -443,
|
|
12
|
+
lineGap: 87,
|
|
13
|
+
unitsPerEm: 2048,
|
|
14
|
+
xWidthAvg: 886
|
|
15
|
+
},
|
|
16
|
+
// Times New Roman Italic almost has the same properties as Times New Roman, we don't include it
|
|
9
17
|
Arial: {
|
|
10
18
|
ascent: 1854,
|
|
11
19
|
descent: -434,
|
|
@@ -13,6 +21,14 @@ const SYSTEM_METRICS = {
|
|
|
13
21
|
unitsPerEm: 2048,
|
|
14
22
|
xWidthAvg: 913
|
|
15
23
|
},
|
|
24
|
+
"Arial Bold": {
|
|
25
|
+
ascent: 1854,
|
|
26
|
+
descent: -434,
|
|
27
|
+
lineGap: 67,
|
|
28
|
+
unitsPerEm: 2048,
|
|
29
|
+
xWidthAvg: 983
|
|
30
|
+
},
|
|
31
|
+
// Arial Italic has the same properties as Arial, we don't include it
|
|
16
32
|
"Courier New": {
|
|
17
33
|
ascent: 1705,
|
|
18
34
|
descent: -615,
|
|
@@ -20,6 +36,8 @@ const SYSTEM_METRICS = {
|
|
|
20
36
|
unitsPerEm: 2048,
|
|
21
37
|
xWidthAvg: 1229
|
|
22
38
|
},
|
|
39
|
+
// Courier New Bold has the same properties as Courier New, we don't include it
|
|
40
|
+
// Courier New Italic has the same properties as Courier New, we don't include it
|
|
23
41
|
BlinkMacSystemFont: {
|
|
24
42
|
ascent: 1980,
|
|
25
43
|
descent: -432,
|
|
@@ -50,17 +68,36 @@ const SYSTEM_METRICS = {
|
|
|
50
68
|
}
|
|
51
69
|
};
|
|
52
70
|
const DEFAULT_FALLBACKS = {
|
|
53
|
-
serif:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
serif: {
|
|
72
|
+
normal: ["Times New Roman"],
|
|
73
|
+
bold: ["Times New Roman Bold"]
|
|
74
|
+
},
|
|
75
|
+
"sans-serif": {
|
|
76
|
+
normal: ["Arial"],
|
|
77
|
+
bold: ["Arial Bold"]
|
|
78
|
+
},
|
|
79
|
+
monospace: { normal: ["Courier New"] },
|
|
80
|
+
"system-ui": {
|
|
81
|
+
normal: ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial"],
|
|
82
|
+
bold: ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial Bold"]
|
|
83
|
+
},
|
|
84
|
+
"ui-serif": {
|
|
85
|
+
normal: ["Times New Roman"],
|
|
86
|
+
bold: ["Times New Roman Bold"]
|
|
87
|
+
},
|
|
88
|
+
"ui-sans-serif": {
|
|
89
|
+
normal: ["Arial"],
|
|
90
|
+
bold: ["Arial Bold"]
|
|
91
|
+
},
|
|
92
|
+
"ui-monospace": { normal: ["Courier New"] }
|
|
60
93
|
};
|
|
61
94
|
class RealSystemFallbacksProvider {
|
|
62
|
-
getLocalFonts(fallback) {
|
|
63
|
-
|
|
95
|
+
getLocalFonts(fallback, variant) {
|
|
96
|
+
const entry = DEFAULT_FALLBACKS[fallback];
|
|
97
|
+
if (!entry) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return entry[variant] ?? entry.normal ?? null;
|
|
64
101
|
}
|
|
65
102
|
getMetricsForLocalFont(family) {
|
|
66
103
|
return SYSTEM_METRICS[family];
|
|
@@ -191,6 +191,7 @@ export interface PreloadData {
|
|
|
191
191
|
}
|
|
192
192
|
export type FontFaceMetrics = Pick<Font, 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg'>;
|
|
193
193
|
export type GenericFallbackName = (typeof GENERIC_FALLBACK_NAMES)[number];
|
|
194
|
+
export type FallbackVariant = 'normal' | 'bold';
|
|
194
195
|
export type Defaults = Required<Pick<ResolvedFontFamily, 'weights' | 'styles' | 'subsets' | 'fallbacks' | 'optimizedFallbacks' | 'formats'>>;
|
|
195
196
|
export interface FontFileData {
|
|
196
197
|
id: string;
|
|
@@ -197,7 +197,7 @@ ${contentConfig.error.message}`
|
|
|
197
197
|
logger.info("Content config changed");
|
|
198
198
|
shouldClear = true;
|
|
199
199
|
}
|
|
200
|
-
if (previousAstroVersion && previousAstroVersion !== "6.4.
|
|
200
|
+
if (previousAstroVersion && previousAstroVersion !== "6.4.3") {
|
|
201
201
|
logger.info("Astro version changed");
|
|
202
202
|
shouldClear = true;
|
|
203
203
|
}
|
|
@@ -205,8 +205,8 @@ ${contentConfig.error.message}`
|
|
|
205
205
|
logger.info("Clearing content store");
|
|
206
206
|
this.#store.clearAll();
|
|
207
207
|
}
|
|
208
|
-
if ("6.4.
|
|
209
|
-
this.#store.metaStore().set("astro-version", "6.4.
|
|
208
|
+
if ("6.4.3") {
|
|
209
|
+
this.#store.metaStore().set("astro-version", "6.4.3");
|
|
210
210
|
}
|
|
211
211
|
if (currentConfigDigest) {
|
|
212
212
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/core/app/base.js
CHANGED
|
@@ -151,6 +151,10 @@ class BaseApp {
|
|
|
151
151
|
return routeData;
|
|
152
152
|
}
|
|
153
153
|
if (routeData.prerender) {
|
|
154
|
+
if (routeData.params.length > 0) {
|
|
155
|
+
const allMatches = this.pipeline.matchAllRoutes(decodeURI(pathname));
|
|
156
|
+
return allMatches.find((r) => !r.prerender);
|
|
157
|
+
}
|
|
154
158
|
return void 0;
|
|
155
159
|
}
|
|
156
160
|
return routeData;
|
|
@@ -29,6 +29,9 @@ export declare const PipelineFeatures: {
|
|
|
29
29
|
readonly i18n: number;
|
|
30
30
|
readonly cache: number;
|
|
31
31
|
};
|
|
32
|
+
/** All feature bits ORed together. Keep next to `PipelineFeatures` so
|
|
33
|
+
* new flags are hard to forget. */
|
|
34
|
+
export declare const ALL_PIPELINE_FEATURES: number;
|
|
32
35
|
/**
|
|
33
36
|
* The `Pipeline` represents the static parts of rendering that do not change between requests.
|
|
34
37
|
* These are mostly known when the server first starts up and do not change.
|
|
@@ -117,6 +120,13 @@ export declare abstract class Pipeline {
|
|
|
117
120
|
* routes or check public assets — use `BaseApp.match()` for that.
|
|
118
121
|
*/
|
|
119
122
|
matchRoute(pathname: string): RouteData | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Returns all routes matching the given pathname, in priority order.
|
|
125
|
+
* Used when the first match cannot serve the request (e.g. a
|
|
126
|
+
* prerendered dynamic route that doesn't cover this specific path)
|
|
127
|
+
* and the caller needs to try subsequent matches.
|
|
128
|
+
*/
|
|
129
|
+
matchAllRoutes(pathname: string): RouteData[];
|
|
120
130
|
/**
|
|
121
131
|
* Rebuilds the internal router after routes have been added or
|
|
122
132
|
* removed (e.g. by the dev server on HMR).
|
|
@@ -21,6 +21,7 @@ const PipelineFeatures = {
|
|
|
21
21
|
i18n: 1 << 4,
|
|
22
22
|
cache: 1 << 5
|
|
23
23
|
};
|
|
24
|
+
const ALL_PIPELINE_FEATURES = PipelineFeatures.redirects | PipelineFeatures.sessions | PipelineFeatures.actions | PipelineFeatures.middleware | PipelineFeatures.i18n | PipelineFeatures.cache;
|
|
24
25
|
class Pipeline {
|
|
25
26
|
internalMiddleware;
|
|
26
27
|
resolvedMiddleware = void 0;
|
|
@@ -123,6 +124,15 @@ class Pipeline {
|
|
|
123
124
|
if (match.type !== "match") return void 0;
|
|
124
125
|
return match.route;
|
|
125
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Returns all routes matching the given pathname, in priority order.
|
|
129
|
+
* Used when the first match cannot serve the request (e.g. a
|
|
130
|
+
* prerendered dynamic route that doesn't cover this specific path)
|
|
131
|
+
* and the caller needs to try subsequent matches.
|
|
132
|
+
*/
|
|
133
|
+
matchAllRoutes(pathname) {
|
|
134
|
+
return this.#router.matchAll(pathname, { allowWithoutBase: true });
|
|
135
|
+
}
|
|
126
136
|
/**
|
|
127
137
|
* Rebuilds the internal router after routes have been added or
|
|
128
138
|
* removed (e.g. by the dev server on HMR).
|
|
@@ -286,6 +296,7 @@ class Pipeline {
|
|
|
286
296
|
}
|
|
287
297
|
}
|
|
288
298
|
export {
|
|
299
|
+
ALL_PIPELINE_FEATURES,
|
|
289
300
|
Pipeline,
|
|
290
301
|
PipelineFeatures
|
|
291
302
|
};
|
|
@@ -35,6 +35,7 @@ function warnDeprecatedMarkdownOptions(config) {
|
|
|
35
35
|
}
|
|
36
36
|
let didWarnAboutLegacyMarkdownPlugins = false;
|
|
37
37
|
let didWarnAboutProcessorMismatch = false;
|
|
38
|
+
const migratedLegacyPluginCounts = /* @__PURE__ */ new WeakMap();
|
|
38
39
|
async function coerceLegacyMarkdownPlugins(config) {
|
|
39
40
|
const md = config?.markdown;
|
|
40
41
|
if (!md) return;
|
|
@@ -48,18 +49,24 @@ async function coerceLegacyMarkdownPlugins(config) {
|
|
|
48
49
|
const current = md.processor;
|
|
49
50
|
if (!current || isUnifiedProcessor(current)) {
|
|
50
51
|
const target = current ?? (md.processor = unified());
|
|
51
|
-
target.options
|
|
52
|
-
|
|
52
|
+
const counts = migratedLegacyPluginCounts.get(target.options) ?? { remark: 0, rehype: 0 };
|
|
53
|
+
if (remarkPlugins.length > counts.remark) {
|
|
54
|
+
target.options.remarkPlugins.push(...remarkPlugins.slice(counts.remark));
|
|
55
|
+
}
|
|
56
|
+
if (rehypePlugins.length > counts.rehype) {
|
|
57
|
+
target.options.rehypePlugins.push(...rehypePlugins.slice(counts.rehype));
|
|
58
|
+
}
|
|
53
59
|
Object.assign(target.options.remarkRehype, remarkRehype);
|
|
60
|
+
migratedLegacyPluginCounts.set(target.options, {
|
|
61
|
+
remark: remarkPlugins.length,
|
|
62
|
+
rehype: rehypePlugins.length
|
|
63
|
+
});
|
|
54
64
|
if (!didWarnAboutLegacyMarkdownPlugins) {
|
|
55
65
|
didWarnAboutLegacyMarkdownPlugins = true;
|
|
56
66
|
console.warn(
|
|
57
67
|
"[astro] `markdown.remarkPlugins`, `markdown.rehypePlugins`, and `markdown.remarkRehype` are deprecated. Pass them to `unified({...})` from `@astrojs/markdown-remark` directly instead."
|
|
58
68
|
);
|
|
59
69
|
}
|
|
60
|
-
delete md.remarkPlugins;
|
|
61
|
-
delete md.rehypePlugins;
|
|
62
|
-
delete md.remarkRehype;
|
|
63
70
|
} else if (!didWarnAboutProcessorMismatch) {
|
|
64
71
|
didWarnAboutProcessorMismatch = true;
|
|
65
72
|
console.warn(
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -37,7 +37,7 @@ async function dev(inlineConfig) {
|
|
|
37
37
|
await telemetry.record([]);
|
|
38
38
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
39
39
|
const logger = restart.container.logger;
|
|
40
|
-
const currentVersion = "6.4.
|
|
40
|
+
const currentVersion = "6.4.3";
|
|
41
41
|
const isPrerelease = currentVersion.includes("-");
|
|
42
42
|
if (!isPrerelease) {
|
|
43
43
|
try {
|
|
@@ -10,7 +10,6 @@ import { AstroCookies } from "../cookies/index.js";
|
|
|
10
10
|
import { Slots } from "../render/index.js";
|
|
11
11
|
import {
|
|
12
12
|
ASTRO_GENERATOR,
|
|
13
|
-
DEFAULT_404_COMPONENT,
|
|
14
13
|
fetchStateSymbol,
|
|
15
14
|
originPathnameSymbol,
|
|
16
15
|
pipelineSymbol,
|
|
@@ -30,7 +29,7 @@ import { Rewrites } from "../rewrites/handler.js";
|
|
|
30
29
|
import { isRoute404or500, isRouteServerIsland } from "../routing/match.js";
|
|
31
30
|
import { normalizeUrl } from "../util/normalized-url.js";
|
|
32
31
|
import { getOriginPathname, setOriginPathname } from "../routing/rewrite.js";
|
|
33
|
-
import { routeHasHtmlExtension } from "../routing/helpers.js";
|
|
32
|
+
import { getCustom404Route, routeHasHtmlExtension } from "../routing/helpers.js";
|
|
34
33
|
import { getRenderOptions } from "../app/render-options.js";
|
|
35
34
|
import { getFirstForwardedValue, validateForwardedHeaders } from "../app/validate-headers.js";
|
|
36
35
|
function getFetchStateFromAPIContext(context) {
|
|
@@ -422,10 +421,8 @@ class FetchState {
|
|
|
422
421
|
}
|
|
423
422
|
return {
|
|
424
423
|
insertDirective(payload) {
|
|
425
|
-
if (state
|
|
424
|
+
if (state.result) {
|
|
426
425
|
state.result.directives = pushDirective(state.result.directives, payload);
|
|
427
|
-
} else {
|
|
428
|
-
state?.result?.directives.push(payload);
|
|
429
426
|
}
|
|
430
427
|
},
|
|
431
428
|
insertScriptResource(resource) {
|
|
@@ -608,16 +605,22 @@ class FetchState {
|
|
|
608
605
|
}
|
|
609
606
|
const matched = pipeline.matchRoute(this.pathname);
|
|
610
607
|
if (matched && matched.prerender && pipeline.manifest.serverLike) {
|
|
611
|
-
|
|
608
|
+
if (matched.params.length > 0) {
|
|
609
|
+
const allMatches = pipeline.matchAllRoutes(this.pathname);
|
|
610
|
+
this.routeData = allMatches.find((r) => !r.prerender);
|
|
611
|
+
} else {
|
|
612
|
+
this.routeData = void 0;
|
|
613
|
+
}
|
|
612
614
|
} else {
|
|
613
615
|
this.routeData = matched;
|
|
614
616
|
}
|
|
615
617
|
pipeline.logger.debug("router", "Astro matched the following route for " + this.request.url);
|
|
616
618
|
pipeline.logger.debug("router", "RouteData:\n" + this.routeData);
|
|
617
619
|
if (!this.routeData) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
620
|
+
const custom404 = getCustom404Route(pipeline.manifestData);
|
|
621
|
+
if (custom404 && !custom404.prerender) {
|
|
622
|
+
this.routeData = custom404;
|
|
623
|
+
}
|
|
621
624
|
}
|
|
622
625
|
if (!this.routeData) {
|
|
623
626
|
pipeline.logger.debug("router", "Astro hasn't found routes that match " + this.request.url);
|
|
@@ -37,6 +37,9 @@ class I18n {
|
|
|
37
37
|
state.pipeline.usedFeatures |= PipelineFeatures.i18n;
|
|
38
38
|
const i18n = this.#i18n;
|
|
39
39
|
const typeHeader = response.headers.get(ROUTE_TYPE_HEADER);
|
|
40
|
+
if (typeHeader) {
|
|
41
|
+
response.headers.delete(ROUTE_TYPE_HEADER);
|
|
42
|
+
}
|
|
40
43
|
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
|
|
41
44
|
if (isReroute === "no" && typeof i18n.fallback === "undefined") {
|
|
42
45
|
return response;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PipelineFeatures } from "../base-pipeline.js";
|
|
2
|
-
import { ROUTE_TYPE_HEADER } from "../constants.js";
|
|
3
2
|
import { attachCookiesToResponse } from "../cookies/index.js";
|
|
4
3
|
import { applyRewriteToState } from "../rewrites/handler.js";
|
|
5
4
|
import { callMiddleware } from "./callMiddleware.js";
|
|
@@ -43,9 +42,6 @@ class AstroMiddleware {
|
|
|
43
42
|
return response;
|
|
44
43
|
}
|
|
45
44
|
#finalize(state, response) {
|
|
46
|
-
if (response.headers.get(ROUTE_TYPE_HEADER)) {
|
|
47
|
-
response.headers.delete(ROUTE_TYPE_HEADER);
|
|
48
|
-
}
|
|
49
45
|
attachCookiesToResponse(response, state.cookies);
|
|
50
46
|
return response;
|
|
51
47
|
}
|
|
@@ -12,7 +12,7 @@ import { PagesHandler } from "../pages/handler.js";
|
|
|
12
12
|
import { renderRedirect } from "../redirects/render.js";
|
|
13
13
|
import { provideSession } from "../session/handler.js";
|
|
14
14
|
import { prepareResponse } from "../app/prepare-response.js";
|
|
15
|
-
import { PipelineFeatures } from "../base-pipeline.js";
|
|
15
|
+
import { ALL_PIPELINE_FEATURES, PipelineFeatures } from "../base-pipeline.js";
|
|
16
16
|
class AstroHandler {
|
|
17
17
|
#app;
|
|
18
18
|
#trailingSlashHandler;
|
|
@@ -64,6 +64,7 @@ class AstroHandler {
|
|
|
64
64
|
return this.#pagesHandler.handle(state, ctx);
|
|
65
65
|
}
|
|
66
66
|
async handle(state) {
|
|
67
|
+
state.pipeline.usedFeatures |= ALL_PIPELINE_FEATURES;
|
|
67
68
|
const trailingSlashRedirect = this.#trailingSlashHandler.handle(state);
|
|
68
69
|
if (trailingSlashRedirect) {
|
|
69
70
|
return trailingSlashRedirect;
|
|
@@ -46,5 +46,13 @@ export declare class Router {
|
|
|
46
46
|
match(inputPathname: string, { allowWithoutBase }?: {
|
|
47
47
|
allowWithoutBase?: boolean;
|
|
48
48
|
}): RouterMatch;
|
|
49
|
+
/**
|
|
50
|
+
* Returns all routes that match the given pathname, in priority order.
|
|
51
|
+
* Used when the first match (e.g. a prerendered route) cannot serve
|
|
52
|
+
* the request and subsequent matches need to be tried.
|
|
53
|
+
*/
|
|
54
|
+
matchAll(inputPathname: string, { allowWithoutBase }?: {
|
|
55
|
+
allowWithoutBase?: boolean;
|
|
56
|
+
}): RouteData[];
|
|
49
57
|
}
|
|
50
58
|
export {};
|
|
@@ -57,6 +57,34 @@ class Router {
|
|
|
57
57
|
const params = getParams(route, pathname);
|
|
58
58
|
return { type: "match", route, params, pathname };
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns all routes that match the given pathname, in priority order.
|
|
62
|
+
* Used when the first match (e.g. a prerendered route) cannot serve
|
|
63
|
+
* the request and subsequent matches need to be tried.
|
|
64
|
+
*/
|
|
65
|
+
matchAll(inputPathname, { allowWithoutBase = false } = {}) {
|
|
66
|
+
const normalized = getRedirectForPathname(inputPathname);
|
|
67
|
+
if (normalized.redirect) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const baseResult = stripBase(
|
|
71
|
+
normalized.pathname,
|
|
72
|
+
this.#base,
|
|
73
|
+
this.#baseWithoutTrailingSlash,
|
|
74
|
+
this.#trailingSlash
|
|
75
|
+
);
|
|
76
|
+
if (!baseResult && !allowWithoutBase) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
let pathname = baseResult ?? normalized.pathname;
|
|
80
|
+
if (this.#buildFormat === "file") {
|
|
81
|
+
pathname = normalizeFileFormatPathname(pathname);
|
|
82
|
+
}
|
|
83
|
+
return this.#routes.filter((candidate) => {
|
|
84
|
+
if (candidate.pattern.test(pathname)) return true;
|
|
85
|
+
return candidate.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
60
88
|
}
|
|
61
89
|
function normalizeBase(base) {
|
|
62
90
|
if (!base) return "/";
|
|
@@ -25,6 +25,14 @@
|
|
|
25
25
|
import { aria, roles } from "aria-query";
|
|
26
26
|
import { AXObjectRoles, elementAXObjects } from "axobject-query";
|
|
27
27
|
const WHITESPACE_REGEX = /\s+/;
|
|
28
|
+
function isHiddenByClosedDetails(element) {
|
|
29
|
+
for (let parent = element.parentElement; parent; parent = parent.parentElement) {
|
|
30
|
+
if (parent.localName !== "details" || parent.open) continue;
|
|
31
|
+
const summary = Array.from(parent.children).find((child) => child.localName === "summary");
|
|
32
|
+
if (!summary?.contains(element)) return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
28
36
|
const a11y_required_attributes = {
|
|
29
37
|
a: ["href"],
|
|
30
38
|
area: ["alt", "aria-label", "aria-labelledby"],
|
|
@@ -321,6 +329,7 @@ const a11y = [
|
|
|
321
329
|
message: "Headings and anchors must have an accessible name, which can come from: inner text, aria-label, aria-labelledby, an img with alt property, or an svg with a tag <title></title>.",
|
|
322
330
|
selector: a11y_required_content.join(","),
|
|
323
331
|
match(element) {
|
|
332
|
+
if (isHiddenByClosedDetails(element)) return false;
|
|
324
333
|
const innerText = element.innerText?.trim();
|
|
325
334
|
if (innerText && innerText !== "") return false;
|
|
326
335
|
const ariaLabel = element.getAttribute("aria-label")?.trim();
|
|
@@ -207,9 +207,9 @@ export type I18nMiddlewareOptions = {
|
|
|
207
207
|
/**
|
|
208
208
|
* @param {AstroConfig['i18n']['routing']} customOptions
|
|
209
209
|
*
|
|
210
|
-
* A function that allows to programmatically create the Astro i18n middleware.
|
|
210
|
+
* A function that allows you to programmatically create the Astro i18n middleware.
|
|
211
211
|
*
|
|
212
|
-
* This is
|
|
212
|
+
* This is useful when you still want to use the default i18n logic, but add only a few exceptions to your website.
|
|
213
213
|
*
|
|
214
214
|
* ## Examples
|
|
215
215
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "6.4.
|
|
3
|
+
"version": "6.4.3",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"clsx": "^2.1.1",
|
|
125
125
|
"common-ancestor-path": "^2.0.0",
|
|
126
126
|
"cookie": "^1.1.1",
|
|
127
|
-
"devalue": "^5.
|
|
127
|
+
"devalue": "^5.8.1",
|
|
128
128
|
"diff": "^8.0.3",
|
|
129
129
|
"dset": "^3.1.4",
|
|
130
130
|
"es-module-lexer": "^2.0.0",
|