astro 7.2.6 → 7.2.8
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/svg/config.d.ts +1 -1
- package/dist/assets/svg/svgo.js +1 -1
- package/dist/assets/svg/types.d.ts +1 -1
- package/dist/assets/svg/utils.js +1 -1
- package/dist/cli/add/cloudflare.d.ts +1 -0
- package/dist/cli/add/cloudflare.js +12 -0
- package/dist/cli/add/index.js +2 -1
- 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.d.ts +5 -8
- package/dist/core/app/base.js +13 -11
- package/dist/core/app/manifest.js +0 -2
- package/dist/core/config/schemas/base.d.ts +1 -1
- package/dist/core/config/schemas/relative.d.ts +3 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/lockfile.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/middleware/sequence.js +9 -12
- package/dist/core/routing/match-request.js +11 -5
- package/dist/core/routing/rewrite.js +3 -2
- package/dist/vite-plugin-app/handle-request.js +6 -1
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from 'zod/v4';
|
|
2
2
|
export declare const SvgOptimizerSchema: z.ZodObject<{
|
|
3
3
|
name: z.ZodString;
|
|
4
|
-
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
4
|
+
optimize: z.ZodCustom<(contents: string, path: string) => string | Promise<string>, (contents: string, path: string) => string | Promise<string>>;
|
|
5
5
|
}, z.core.$strip>;
|
package/dist/assets/svg/svgo.js
CHANGED
package/dist/assets/svg/utils.js
CHANGED
|
@@ -9,7 +9,7 @@ async function parseSvg({
|
|
|
9
9
|
let processedContents = contents;
|
|
10
10
|
if (svgOptimizer) {
|
|
11
11
|
try {
|
|
12
|
-
processedContents = await svgOptimizer.optimize(contents);
|
|
12
|
+
processedContents = await svgOptimizer.optimize(contents, path);
|
|
13
13
|
} catch (cause) {
|
|
14
14
|
throw new AstroError(
|
|
15
15
|
{
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getCloudflareCompatibilityDate(root: URL): Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
async function getCloudflareCompatibilityDate(root) {
|
|
4
|
+
const require2 = createRequire(root);
|
|
5
|
+
const infoPath = require2.resolve("@astrojs/cloudflare/info");
|
|
6
|
+
const infoUrl = pathToFileURL(infoPath).toString();
|
|
7
|
+
const infoModule = await import(infoUrl);
|
|
8
|
+
return infoModule.getLocalWorkerdCompatibilityDate().date;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
getCloudflareCompatibilityDate
|
|
12
|
+
};
|
package/dist/cli/add/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import { eventCliSession, telemetry } from "../../events/index.js";
|
|
|
28
28
|
import { exec } from "../exec.js";
|
|
29
29
|
import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
|
|
30
30
|
import { fetchPackageJson, fetchPackageVersions } from "../install-package.js";
|
|
31
|
+
import { getCloudflareCompatibilityDate } from "./cloudflare.js";
|
|
31
32
|
const { bold, cyan, dim, green, magenta, red, yellow } = colors;
|
|
32
33
|
const ALIASES = /* @__PURE__ */ new Map([
|
|
33
34
|
["solid", "solid-js"],
|
|
@@ -167,7 +168,7 @@ async function add(names, { flags }) {
|
|
|
167
168
|
);
|
|
168
169
|
if (await askToContinue({ flags, logger })) {
|
|
169
170
|
const data = await getPackageJson();
|
|
170
|
-
|
|
171
|
+
const compatibilityDate = await getCloudflareCompatibilityDate(root);
|
|
171
172
|
await fs.writeFile(
|
|
172
173
|
wranglerConfigURL,
|
|
173
174
|
STUBS.CLOUDFLARE_WRANGLER_CONFIG(data?.name ?? "example", compatibilityDate),
|
|
@@ -196,7 +196,7 @@ ${contentConfig.error.message}`
|
|
|
196
196
|
logger.info("Content config changed");
|
|
197
197
|
shouldClear = true;
|
|
198
198
|
}
|
|
199
|
-
if (previousAstroVersion && previousAstroVersion !== "7.2.
|
|
199
|
+
if (previousAstroVersion && previousAstroVersion !== "7.2.8") {
|
|
200
200
|
logger.info("Astro version changed");
|
|
201
201
|
shouldClear = true;
|
|
202
202
|
}
|
|
@@ -204,8 +204,8 @@ ${contentConfig.error.message}`
|
|
|
204
204
|
logger.info("Clearing content store");
|
|
205
205
|
this.#store.clearAll();
|
|
206
206
|
}
|
|
207
|
-
if ("7.2.
|
|
208
|
-
this.#store.metaStore().set("astro-version", "7.2.
|
|
207
|
+
if ("7.2.8") {
|
|
208
|
+
this.#store.metaStore().set("astro-version", "7.2.8");
|
|
209
209
|
}
|
|
210
210
|
if (currentConfigDigest) {
|
|
211
211
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/core/app/base.d.ts
CHANGED
|
@@ -144,14 +144,11 @@ export declare abstract class BaseApp {
|
|
|
144
144
|
set setManifestData(newManifestData: RoutesList);
|
|
145
145
|
removeBase(pathname: string): string;
|
|
146
146
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
* middleware can't catch.
|
|
153
|
-
*/
|
|
154
|
-
private safeDecodeURI;
|
|
147
|
+
* Fully decodes a pathname, falling back to a single decode and then the raw pathname
|
|
148
|
+
* when validation fails. Adapter matching runs before `render()`, so it must not throw
|
|
149
|
+
* for request input that render-time validation handles.
|
|
150
|
+
*/
|
|
151
|
+
private safeDecodePathname;
|
|
155
152
|
/**
|
|
156
153
|
* Extracts the base-stripped, decoded pathname from a request.
|
|
157
154
|
* Used by adapters to compute the pathname for dev-mode route matching.
|
package/dist/core/app/base.js
CHANGED
|
@@ -18,6 +18,7 @@ import { handleRequest } from "../routing/handler.js";
|
|
|
18
18
|
import { getDefaultStatusCode } from "../routing/helpers.js";
|
|
19
19
|
import { matchRequest } from "../routing/match-request.js";
|
|
20
20
|
import { getRouteTable, matchRoute, updateRouteTable } from "../routing/route-table.js";
|
|
21
|
+
import { validateAndDecodePathname } from "../util/pathname.js";
|
|
21
22
|
import { setRenderOptions } from "./render-options.js";
|
|
22
23
|
class BaseApp {
|
|
23
24
|
manifest;
|
|
@@ -149,19 +150,20 @@ class BaseApp {
|
|
|
149
150
|
return stripRequestBase(pathname, this.manifest.base);
|
|
150
151
|
}
|
|
151
152
|
/**
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* `URIError: URI malformed`, and because `match()` runs before `render()` that error
|
|
156
|
-
* escapes the adapter's request handler as an uncaught exception (HTTP 500) that user
|
|
157
|
-
* middleware can't catch.
|
|
153
|
+
* Fully decodes a pathname, falling back to a single decode and then the raw pathname
|
|
154
|
+
* when validation fails. Adapter matching runs before `render()`, so it must not throw
|
|
155
|
+
* for request input that render-time validation handles.
|
|
158
156
|
*/
|
|
159
|
-
|
|
157
|
+
safeDecodePathname(pathname) {
|
|
160
158
|
try {
|
|
161
|
-
return
|
|
159
|
+
return validateAndDecodePathname(pathname);
|
|
162
160
|
} catch (e) {
|
|
163
161
|
this.adapterLogger.debug(e.toString());
|
|
164
|
-
|
|
162
|
+
try {
|
|
163
|
+
return decodeURI(pathname);
|
|
164
|
+
} catch {
|
|
165
|
+
return pathname;
|
|
166
|
+
}
|
|
165
167
|
}
|
|
166
168
|
}
|
|
167
169
|
/**
|
|
@@ -171,7 +173,7 @@ class BaseApp {
|
|
|
171
173
|
getPathnameFromRequest(request) {
|
|
172
174
|
const url = new URL(request.url);
|
|
173
175
|
const pathname = prependForwardSlash(this.removeBase(url.pathname));
|
|
174
|
-
return this.
|
|
176
|
+
return this.safeDecodePathname(pathname);
|
|
175
177
|
}
|
|
176
178
|
/**
|
|
177
179
|
* Given a `Request`, it returns the `RouteData` that matches its `pathname`. By default, prerendered
|
|
@@ -243,7 +245,7 @@ class BaseApp {
|
|
|
243
245
|
if (!routeData) {
|
|
244
246
|
const domainPathname = this.computePathnameFromDomain(request);
|
|
245
247
|
if (domainPathname) {
|
|
246
|
-
routeData = matchRoute(this.manifest, this.
|
|
248
|
+
routeData = matchRoute(this.manifest, this.safeDecodePathname(domainPathname));
|
|
247
249
|
}
|
|
248
250
|
}
|
|
249
251
|
const resolvedOptions = {
|
|
@@ -8,8 +8,6 @@ function deserializeManifest(serializedManifest, routesList) {
|
|
|
8
8
|
...serializedRoute,
|
|
9
9
|
routeData: deserializeRouteData(serializedRoute.routeData)
|
|
10
10
|
});
|
|
11
|
-
const route = serializedRoute;
|
|
12
|
-
route.routeData = deserializeRouteData(serializedRoute.routeData);
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
if (routesList) {
|
|
@@ -487,7 +487,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
487
487
|
incrementalBuild: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
488
488
|
svgOptimizer: z.ZodOptional<z.ZodObject<{
|
|
489
489
|
name: z.ZodString;
|
|
490
|
-
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
490
|
+
optimize: z.ZodCustom<(contents: string, path: string) => string | Promise<string>, (contents: string, path: string) => string | Promise<string>>;
|
|
491
491
|
}, z.core.$strip>>;
|
|
492
492
|
collectionStorage: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"single-file">, z.ZodLiteral<"chunked">, z.ZodObject<{
|
|
493
493
|
type: z.ZodLiteral<"chunked">;
|
|
@@ -439,7 +439,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
439
439
|
incrementalBuild: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
440
440
|
svgOptimizer: z.ZodOptional<z.ZodObject<{
|
|
441
441
|
name: z.ZodString;
|
|
442
|
-
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
442
|
+
optimize: z.ZodCustom<(contents: string, path: string) => string | Promise<string>, (contents: string, path: string) => string | Promise<string>>;
|
|
443
443
|
}, z.core.$strip>>;
|
|
444
444
|
collectionStorage: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"single-file">, z.ZodLiteral<"chunked">, z.ZodObject<{
|
|
445
445
|
type: z.ZodLiteral<"chunked">;
|
|
@@ -638,7 +638,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
638
638
|
};
|
|
639
639
|
svgOptimizer?: {
|
|
640
640
|
name: string;
|
|
641
|
-
optimize: (contents: string) => string | Promise<string>;
|
|
641
|
+
optimize: (contents: string, path: string) => string | Promise<string>;
|
|
642
642
|
} | undefined;
|
|
643
643
|
};
|
|
644
644
|
legacy: {
|
|
@@ -905,7 +905,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
905
905
|
};
|
|
906
906
|
svgOptimizer?: {
|
|
907
907
|
name: string;
|
|
908
|
-
optimize: (contents: string) => string | Promise<string>;
|
|
908
|
+
optimize: (contents: string, path: string) => string | Promise<string>;
|
|
909
909
|
} | undefined;
|
|
910
910
|
};
|
|
911
911
|
legacy: {
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "7.2.
|
|
29
|
+
const currentVersion = "7.2.8";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import findProcess from "find-
|
|
3
|
+
import findProcess from "find-proc";
|
|
4
4
|
const GRACEFUL_SHUTDOWN_TIMEOUT = 5e3;
|
|
5
5
|
function getLockFileURL(root, command = "dev") {
|
|
6
6
|
return new URL(`.astro/${command}.json`, root);
|
|
@@ -3,7 +3,7 @@ import { getEnvironment } from "../environment/index.js";
|
|
|
3
3
|
import { ForbiddenRewrite } from "../errors/errors-data.js";
|
|
4
4
|
import { AstroError } from "../errors/index.js";
|
|
5
5
|
import { getParams } from "../render/params-and-props.js";
|
|
6
|
-
import { setOriginPathname } from "../routing/rewrite.js";
|
|
6
|
+
import { copyRequest, setOriginPathname } from "../routing/rewrite.js";
|
|
7
7
|
import { defineMiddleware } from "./defineMiddleware.js";
|
|
8
8
|
function sequence(...handlers) {
|
|
9
9
|
const filtered = handlers.filter((h) => !!h);
|
|
@@ -21,17 +21,6 @@ function sequence(...handlers) {
|
|
|
21
21
|
const result = handle(handleContext, async (payload) => {
|
|
22
22
|
if (i < length - 1) {
|
|
23
23
|
if (payload) {
|
|
24
|
-
let newRequest;
|
|
25
|
-
if (payload instanceof Request) {
|
|
26
|
-
newRequest = payload;
|
|
27
|
-
} else if (payload instanceof URL) {
|
|
28
|
-
newRequest = new Request(payload, handleContext.request.clone());
|
|
29
|
-
} else {
|
|
30
|
-
newRequest = new Request(
|
|
31
|
-
new URL(payload, handleContext.url.origin),
|
|
32
|
-
handleContext.request.clone()
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
24
|
const oldPathname = handleContext.url.pathname;
|
|
36
25
|
const state = Reflect.get(handleContext, fetchStateSymbol);
|
|
37
26
|
if (!state) {
|
|
@@ -45,6 +34,14 @@ function sequence(...handlers) {
|
|
|
45
34
|
payload,
|
|
46
35
|
handleContext.request
|
|
47
36
|
);
|
|
37
|
+
let newRequest;
|
|
38
|
+
if (payload instanceof Request) {
|
|
39
|
+
newRequest = payload;
|
|
40
|
+
} else {
|
|
41
|
+
const request = handleContext.request.method === "GET" || handleContext.request.method === "HEAD" ? handleContext.request : handleContext.request.clone();
|
|
42
|
+
const newUrl = payload instanceof URL ? payload : new URL(payload, handleContext.url.origin);
|
|
43
|
+
newRequest = copyRequest(newUrl, request, false, state.logger, routeData.route);
|
|
44
|
+
}
|
|
48
45
|
if (manifest.serverLike === true && handleContext.isPrerendered === false && routeData.prerender === true) {
|
|
49
46
|
throw new AstroError({
|
|
50
47
|
...ForbiddenRewrite,
|
|
@@ -2,15 +2,20 @@ import { prependForwardSlash, stripRequestBase } from "@astrojs/internal-helpers
|
|
|
2
2
|
import { computePathnameFromDomain } from "../i18n/domain.js";
|
|
3
3
|
import { AstroIntegrationLogger } from "../logger/core.js";
|
|
4
4
|
import { getLogger } from "../logger/manifest-logger.js";
|
|
5
|
+
import { validateAndDecodePathname } from "../util/pathname.js";
|
|
5
6
|
import { matchAllRoutes, matchRoute } from "./route-table.js";
|
|
6
|
-
function
|
|
7
|
+
function safeDecodePathname(manifest, pathname) {
|
|
7
8
|
try {
|
|
8
|
-
return
|
|
9
|
+
return validateAndDecodePathname(pathname);
|
|
9
10
|
} catch (e) {
|
|
10
11
|
new AstroIntegrationLogger(getLogger(manifest).options, manifest.adapterName).debug(
|
|
11
12
|
e.toString()
|
|
12
13
|
);
|
|
13
|
-
|
|
14
|
+
try {
|
|
15
|
+
return decodeURI(pathname);
|
|
16
|
+
} catch {
|
|
17
|
+
return pathname;
|
|
18
|
+
}
|
|
14
19
|
}
|
|
15
20
|
}
|
|
16
21
|
function matchRequest(manifest, request, allowPrerenderedRoutes = false) {
|
|
@@ -27,14 +32,15 @@ function matchRequest(manifest, request, allowPrerenderedRoutes = false) {
|
|
|
27
32
|
if (!pathname) {
|
|
28
33
|
pathname = prependForwardSlash(stripRequestBase(url.pathname, manifest.base));
|
|
29
34
|
}
|
|
30
|
-
|
|
35
|
+
pathname = safeDecodePathname(manifest, pathname);
|
|
36
|
+
const routeData = matchRoute(manifest, pathname);
|
|
31
37
|
if (!routeData) return void 0;
|
|
32
38
|
if (allowPrerenderedRoutes) {
|
|
33
39
|
return routeData;
|
|
34
40
|
}
|
|
35
41
|
if (routeData.prerender) {
|
|
36
42
|
if (routeData.params.length > 0) {
|
|
37
|
-
const allMatches = matchAllRoutes(manifest,
|
|
43
|
+
const allMatches = matchAllRoutes(manifest, pathname);
|
|
38
44
|
return allMatches.find((r) => !r.prerender);
|
|
39
45
|
}
|
|
40
46
|
return void 0;
|
|
@@ -80,13 +80,14 @@ function findRouteToRewrite({
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
function copyRequest(newUrl, oldRequest, isPrerendered, logger, routePattern) {
|
|
83
|
-
|
|
83
|
+
const canHaveBody = oldRequest.method !== "GET" && oldRequest.method !== "HEAD";
|
|
84
|
+
if (canHaveBody && oldRequest.bodyUsed) {
|
|
84
85
|
throw new AstroError(AstroErrorData.RewriteWithBodyUsed);
|
|
85
86
|
}
|
|
86
87
|
return createRequest({
|
|
87
88
|
url: newUrl,
|
|
88
89
|
method: oldRequest.method,
|
|
89
|
-
body: oldRequest.body,
|
|
90
|
+
body: canHaveBody ? oldRequest.body : void 0,
|
|
90
91
|
isPrerendered,
|
|
91
92
|
logger,
|
|
92
93
|
headers: isPrerendered ? {} : oldRequest.headers,
|
|
@@ -5,6 +5,7 @@ import { getEnvironment, setEnvironment } from "../core/environment/index.js";
|
|
|
5
5
|
import { createSafeError } from "../core/errors/index.js";
|
|
6
6
|
import { setLogger } from "../core/logger/manifest-logger.js";
|
|
7
7
|
import { createRequest } from "../core/request.js";
|
|
8
|
+
import { validateAndDecodePathname } from "../core/util/pathname.js";
|
|
8
9
|
import { SERIALIZED_MANIFEST_ID } from "../manifest/serialized.js";
|
|
9
10
|
import { recordServerError } from "../vite-plugin-astro-server/error.js";
|
|
10
11
|
import { runWithErrorHandling } from "../vite-plugin-astro-server/index.js";
|
|
@@ -39,7 +40,11 @@ async function handleDevRequest(app, deps, { incomingRequest, incomingResponse,
|
|
|
39
40
|
if (manifest.trailingSlash === "never" && !incomingRequest.url) {
|
|
40
41
|
pathname = "";
|
|
41
42
|
} else {
|
|
42
|
-
|
|
43
|
+
try {
|
|
44
|
+
pathname = validateAndDecodePathname(url.pathname);
|
|
45
|
+
} catch {
|
|
46
|
+
pathname = decodeURI(url.pathname);
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
url.pathname = removeTrailingForwardSlash(manifest.base) + url.pathname;
|
|
45
50
|
if (url.pathname.endsWith("/") && !shouldAppendForwardSlash(manifest.trailingSlash, manifest.buildFormat)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.8",
|
|
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",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"dset": "^3.1.4",
|
|
120
120
|
"es-module-lexer": "^2.0.0",
|
|
121
121
|
"esbuild": "^0.28.0",
|
|
122
|
-
"find-
|
|
122
|
+
"find-proc": "0.1.0",
|
|
123
123
|
"flattie": "^1.1.1",
|
|
124
124
|
"fontace": "~0.4.1",
|
|
125
125
|
"get-tsconfig": "5.0.0-beta.4",
|
|
@@ -153,12 +153,12 @@
|
|
|
153
153
|
"xxhash-wasm": "^1.1.0",
|
|
154
154
|
"yargs-parser": "^22.0.0",
|
|
155
155
|
"zod": "^4.3.6",
|
|
156
|
-
"@astrojs/internal-helpers": "0.10.4",
|
|
157
156
|
"@astrojs/markdown-satteri": "0.3.8",
|
|
157
|
+
"@astrojs/internal-helpers": "0.10.4",
|
|
158
158
|
"@astrojs/telemetry": "3.3.3"
|
|
159
159
|
},
|
|
160
160
|
"optionalDependencies": {
|
|
161
|
-
"sharp": "^0.
|
|
161
|
+
"sharp": "^0.35.4"
|
|
162
162
|
},
|
|
163
163
|
"peerDependencies": {
|
|
164
164
|
"@astrojs/markdown-remark": "7.2.4"
|