astro 7.0.0-alpha.0 → 7.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Code.astro +1 -1
- package/dist/actions/handler.d.ts +32 -0
- package/dist/actions/handler.js +45 -0
- package/dist/actions/runtime/server.js +1 -1
- package/dist/assets/build/generate.js +1 -1
- package/dist/assets/build/remote.d.ts +3 -2
- package/dist/assets/build/remote.js +16 -9
- package/dist/assets/endpoint/dev.js +1 -1
- package/dist/assets/endpoint/generic.js +8 -20
- package/dist/assets/endpoint/loadImage.d.ts +11 -0
- package/dist/assets/endpoint/loadImage.js +19 -0
- package/dist/assets/endpoint/shared.js +7 -2
- package/dist/assets/fonts/config.d.ts +4 -4
- 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/assets/index.d.ts +1 -0
- package/dist/assets/index.js +2 -0
- package/dist/assets/internal.js +22 -3
- package/dist/assets/services/service.d.ts +1 -1
- package/dist/assets/services/service.js +9 -9
- package/dist/assets/services/sharp.js +53 -18
- package/dist/assets/utils/generateImageStylesCSS.js +26 -6
- package/dist/assets/utils/index.d.ts +1 -0
- package/dist/assets/utils/index.js +2 -0
- package/dist/assets/utils/inferSourceFormat.d.ts +8 -3
- package/dist/assets/utils/inferSourceFormat.js +15 -4
- package/dist/assets/utils/metadata.js +1 -1
- package/dist/assets/utils/redirectValidation.d.ts +48 -0
- package/dist/assets/utils/redirectValidation.js +48 -0
- package/dist/assets/utils/remoteProbe.js +25 -2
- package/dist/assets/utils/vendor/image-size/types/svg.js +1 -1
- package/dist/cli/add/index.js +7 -58
- package/dist/cli/dev/background.d.ts +16 -0
- package/dist/cli/dev/background.js +116 -0
- package/dist/cli/dev/index.js +82 -3
- package/dist/cli/dev/logs.d.ts +6 -0
- package/dist/cli/dev/logs.js +72 -0
- package/dist/cli/dev/status.d.ts +15 -0
- package/dist/cli/dev/status.js +27 -0
- package/dist/cli/dev/stop.d.ts +12 -0
- package/dist/cli/dev/stop.js +43 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +18 -14
- package/dist/content/content-layer.js +16 -11
- package/dist/content/data-store.d.ts +1 -1
- package/dist/content/loaders/types.d.ts +1 -1
- package/dist/content/runtime-assets.d.ts +2 -2
- package/dist/content/runtime.d.ts +1 -1
- package/dist/content/runtime.js +9 -4
- package/dist/content/server-listeners.js +0 -4
- package/dist/content/types-generator.js +5 -1
- package/dist/content/utils.d.ts +1 -1
- package/dist/content/utils.js +1 -1
- package/dist/content/vite-plugin-content-assets.js +1 -0
- package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
- package/dist/core/app/base.d.ts +42 -15
- package/dist/core/app/base.js +151 -375
- package/dist/core/app/dev/app.d.ts +3 -2
- package/dist/core/app/dev/app.js +4 -60
- package/dist/core/app/entrypoints/node.d.ts +1 -1
- package/dist/core/app/entrypoints/node.js +2 -0
- package/dist/core/app/entrypoints/virtual/dev.js +2 -0
- package/dist/core/app/entrypoints/virtual/prod.js +4 -1
- package/dist/core/app/node.d.ts +16 -0
- package/dist/core/app/node.js +59 -13
- package/dist/core/app/prepare-response.d.ts +11 -0
- package/dist/core/app/prepare-response.js +18 -0
- package/dist/core/app/render-options.d.ts +11 -0
- package/dist/core/app/render-options.js +11 -0
- package/dist/core/base-pipeline.d.ts +48 -1
- package/dist/core/base-pipeline.js +63 -8
- package/dist/core/build/app.d.ts +3 -4
- package/dist/core/build/app.js +3 -17
- package/dist/core/build/generate.js +8 -1
- package/dist/core/build/index.d.ts +0 -11
- package/dist/core/build/index.js +0 -3
- package/dist/core/build/internal.d.ts +7 -0
- package/dist/core/build/plugins/plugin-chunk-imports.d.ts +6 -0
- package/dist/core/build/plugins/plugin-chunk-imports.js +29 -17
- package/dist/core/build/plugins/plugin-css.js +40 -1
- package/dist/core/build/plugins/plugin-internals.js +1 -1
- package/dist/core/build/plugins/plugin-manifest.js +11 -1
- package/dist/core/build/static-build.js +22 -141
- package/dist/core/build/types.d.ts +0 -1
- package/dist/core/build/util.js +8 -1
- package/dist/core/build/vite-build-config.d.ts +28 -0
- package/dist/core/build/vite-build-config.js +165 -0
- package/dist/core/cache/handler.d.ts +29 -0
- package/dist/core/cache/handler.js +81 -0
- package/dist/core/compile/style.js +18 -1
- package/dist/core/config/index.d.ts +1 -1
- package/dist/core/config/index.js +4 -1
- package/dist/core/config/merge.js +4 -0
- package/dist/core/config/schemas/base.d.ts +25 -13
- package/dist/core/config/schemas/base.js +39 -10
- package/dist/core/config/schemas/relative.d.ts +76 -49
- package/dist/core/config/schemas/relative.js +2 -3
- package/dist/core/config/settings.js +2 -4
- package/dist/core/config/tsconfig.d.ts +24 -9
- package/dist/core/config/tsconfig.js +54 -45
- package/dist/core/config/validate.js +59 -0
- package/dist/core/constants.d.ts +27 -1
- package/dist/core/constants.js +14 -1
- package/dist/core/cookies/cookies.d.ts +7 -2
- package/dist/core/cookies/cookies.js +11 -4
- package/dist/core/cookies/response.d.ts +1 -1
- package/dist/core/cookies/response.js +1 -2
- package/dist/core/create-vite.js +18 -1
- package/dist/core/csp/config.js +17 -5
- package/dist/core/csp/runtime.js +6 -4
- package/dist/core/dev/dev.d.ts +1 -0
- package/dist/core/dev/dev.js +4 -13
- package/dist/core/dev/lockfile.d.ts +54 -0
- package/dist/core/dev/lockfile.js +93 -0
- package/dist/core/errors/build-handler.d.ts +17 -0
- package/dist/core/errors/build-handler.js +22 -0
- package/dist/core/errors/default-handler.d.ts +14 -0
- package/dist/core/errors/default-handler.js +144 -0
- package/dist/core/errors/dev-handler.d.ts +21 -0
- package/dist/core/errors/dev-handler.js +82 -0
- package/dist/core/errors/errors-data.d.ts +43 -38
- package/dist/core/errors/errors-data.js +79 -73
- package/dist/core/errors/handler.d.ts +9 -0
- package/dist/core/errors/handler.js +0 -0
- package/dist/core/errors/zod-error-map.js +30 -1
- package/dist/core/fetch/default-handler.d.ts +17 -0
- package/dist/core/fetch/default-handler.js +45 -0
- package/dist/core/fetch/fetch-state.d.ts +230 -0
- package/dist/core/fetch/fetch-state.js +896 -0
- package/dist/core/fetch/index.d.ts +61 -0
- package/dist/core/fetch/index.js +121 -0
- package/dist/core/fetch/types.d.ts +25 -0
- package/dist/core/fetch/types.js +0 -0
- package/dist/core/fetch/vite-plugin.d.ts +5 -0
- package/dist/core/fetch/vite-plugin.js +76 -0
- package/dist/core/hono/index.d.ts +21 -0
- package/dist/core/hono/index.js +101 -0
- package/dist/core/i18n/domain.d.ts +12 -0
- package/dist/core/i18n/domain.js +66 -0
- package/dist/core/i18n/handler.d.ts +18 -0
- package/dist/core/i18n/handler.js +122 -0
- package/dist/core/logger/core.d.ts +9 -1
- package/dist/core/logger/core.js +17 -1
- package/dist/core/messages/runtime.d.ts +0 -3
- package/dist/core/messages/runtime.js +1 -9
- package/dist/core/middleware/astro-middleware.d.ts +27 -0
- package/dist/core/middleware/astro-middleware.js +51 -0
- package/dist/core/module-loader/vite.js +1 -2
- package/dist/core/pages/handler.d.ts +20 -0
- package/dist/core/pages/handler.js +75 -0
- package/dist/core/preview/index.js +6 -5
- package/dist/core/preview/static-preview-server.js +5 -2
- package/dist/core/redirects/render.d.ts +2 -2
- package/dist/core/redirects/render.js +7 -8
- package/dist/core/render/params-and-props.js +2 -2
- package/dist/core/render/route-cache.d.ts +1 -0
- package/dist/core/render/route-cache.js +4 -4
- package/dist/core/render/slots.js +9 -2
- package/dist/core/rewrites/handler.d.ts +37 -0
- package/dist/core/rewrites/handler.js +67 -0
- package/dist/core/routing/3xx.js +8 -4
- package/dist/core/routing/create-manifest.js +11 -1
- package/dist/core/routing/handler.d.ts +17 -0
- package/dist/core/routing/handler.js +171 -0
- package/dist/core/routing/match.d.ts +0 -7
- package/dist/core/routing/match.js +0 -5
- package/dist/core/routing/parse-route.js +1 -1
- package/dist/core/routing/pattern.js +1 -1
- package/dist/core/routing/rewrite.js +2 -5
- package/dist/core/routing/router.d.ts +8 -0
- package/dist/core/routing/router.js +28 -0
- package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
- package/dist/core/routing/trailing-slash-handler.js +67 -0
- package/dist/core/routing/validation.js +1 -1
- package/dist/core/server-islands/vite-plugin-server-islands.d.ts +6 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +13 -3
- package/dist/core/session/config.d.ts +1 -1
- package/dist/core/session/drivers.d.ts +1 -1
- package/dist/core/session/handler.d.ts +11 -0
- package/dist/core/session/handler.js +33 -0
- package/dist/core/session/runtime.js +7 -2
- package/dist/core/util/normalized-url.d.ts +10 -0
- package/dist/core/util/normalized-url.js +24 -0
- package/dist/core/util/pathname.d.ts +10 -1
- package/dist/core/util/pathname.js +13 -4
- package/dist/environments.js +1 -1
- package/dist/events/session.d.ts +8 -0
- package/dist/events/session.js +11 -0
- package/dist/i18n/middleware.d.ts +10 -0
- package/dist/i18n/middleware.js +4 -88
- package/dist/i18n/utils.js +2 -2
- package/dist/jsx/rehype.d.ts +1 -1
- package/dist/manifest/virtual-module.js +3 -1
- package/dist/markdown/index.d.ts +4 -0
- package/dist/markdown/index.js +14 -0
- package/dist/prefetch/index.js +12 -7
- package/dist/prerender/utils.js +5 -1
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +9 -0
- package/dist/runtime/server/astro-island.js +57 -20
- package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
- package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt.js +1 -1
- package/dist/runtime/server/jsx.js +1 -1
- package/dist/runtime/server/render/common.js +10 -4
- package/dist/runtime/server/render/component.js +8 -6
- package/dist/runtime/server/render/head.js +1 -5
- package/dist/runtime/server/render/server-islands.js +2 -1
- package/dist/runtime/server/render/util.js +2 -2
- package/dist/runtime/server/scripts.js +6 -0
- package/dist/runtime/server/transition.d.ts +1 -6
- package/dist/runtime/server/transition.js +0 -8
- package/dist/transitions/events.d.ts +0 -14
- package/dist/transitions/events.js +0 -14
- package/dist/transitions/index.d.ts +0 -1
- package/dist/transitions/index.js +0 -2
- package/dist/transitions/vite-plugin-transitions.js +2 -4
- package/dist/types/public/config.d.ts +96 -14
- package/dist/types/public/content.d.ts +5 -5
- package/dist/types/public/index.d.ts +2 -1
- package/dist/types/public/integrations.d.ts +11 -3
- package/dist/types/public/internal.d.ts +1 -1
- package/dist/types/public/manifest.d.ts +1 -1
- package/dist/virtual-modules/i18n.d.ts +2 -2
- package/dist/virtual-modules/i18n.js +1 -1
- package/dist/vite-plugin-app/app.d.ts +13 -6
- package/dist/vite-plugin-app/app.js +51 -89
- package/dist/vite-plugin-app/createAstroServerApp.d.ts +3 -1
- package/dist/vite-plugin-app/createAstroServerApp.js +4 -3
- package/dist/vite-plugin-astro-server/plugin.js +11 -5
- package/dist/vite-plugin-astro-server/route-guard.d.ts +33 -0
- package/dist/vite-plugin-astro-server/route-guard.js +42 -23
- package/dist/vite-plugin-dev-status/index.d.ts +2 -0
- package/dist/vite-plugin-dev-status/index.js +15 -0
- package/dist/vite-plugin-head/index.js +36 -19
- package/dist/vite-plugin-hmr-reload/index.d.ts +1 -1
- package/dist/vite-plugin-hmr-reload/index.js +23 -1
- package/dist/vite-plugin-integrations-container/index.js +15 -6
- package/dist/vite-plugin-markdown/content-entry-type.js +7 -4
- package/dist/vite-plugin-markdown/images.js +9 -11
- package/dist/vite-plugin-markdown/index.js +12 -11
- package/dist/vite-plugin-utils/index.d.ts +1 -0
- package/dist/vite-plugin-utils/index.js +10 -1
- package/package.json +23 -16
- package/templates/content/types.d.ts +1 -0
- package/types/transitions.d.ts +0 -7
- package/dist/core/render-context.d.ts +0 -77
- package/dist/core/render-context.js +0 -826
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
|
|
2
2
|
import { BaseApp } from "../core/app/entrypoints/index.js";
|
|
3
|
-
import { getFirstForwardedValue, validateForwardedHeaders } from "../core/app/validate-headers.js";
|
|
4
3
|
import { shouldAppendForwardSlash } from "../core/build/util.js";
|
|
5
4
|
import { clientLocalsSymbol } from "../core/constants.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
MiddlewareNotAResponse
|
|
9
|
-
} from "../core/errors/errors-data.js";
|
|
10
|
-
import { createSafeError, isAstroError } from "../core/errors/index.js";
|
|
5
|
+
import { createSafeError } from "../core/errors/index.js";
|
|
6
|
+
import { DevErrorHandler } from "../core/errors/dev-handler.js";
|
|
11
7
|
import { createRequest } from "../core/request.js";
|
|
12
8
|
import { recordServerError } from "../vite-plugin-astro-server/error.js";
|
|
13
9
|
import { runWithErrorHandling } from "../vite-plugin-astro-server/index.js";
|
|
14
10
|
import { handle500Response, writeSSRResult } from "../vite-plugin-astro-server/response.js";
|
|
15
11
|
import { RunnablePipeline } from "./pipeline.js";
|
|
16
|
-
import { getCustom404Route, getCustom500Route } from "../core/routing/helpers.js";
|
|
17
12
|
import { ensure404Route } from "../core/routing/astro-designed-error-pages.js";
|
|
18
13
|
import { matchRoute } from "../core/routing/dev.js";
|
|
19
14
|
import { req } from "../core/messages/runtime.js";
|
|
@@ -21,13 +16,27 @@ class AstroServerApp extends BaseApp {
|
|
|
21
16
|
settings;
|
|
22
17
|
loader;
|
|
23
18
|
manifestData;
|
|
24
|
-
currentRenderContext = void 0;
|
|
25
19
|
constructor(manifest, streaming = true, logger, manifestData, loader, settings, getDebugInfo) {
|
|
26
20
|
super(manifest, streaming, settings, logger, loader, manifestData, getDebugInfo);
|
|
27
21
|
this.settings = settings;
|
|
28
22
|
this.loader = loader;
|
|
29
23
|
this.manifestData = manifestData;
|
|
30
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Loads the user's `src/app.ts` (via `virtual:astro:fetchable`) and
|
|
27
|
+
* sets it as the fetch handler. Called on every request so that HMR
|
|
28
|
+
* invalidation of the virtual module is picked up automatically.
|
|
29
|
+
* Vite caches the module internally so repeated calls are cheap.
|
|
30
|
+
*/
|
|
31
|
+
async #loadFetchHandler() {
|
|
32
|
+
try {
|
|
33
|
+
const mod = await this.loader.import("virtual:astro:fetchable");
|
|
34
|
+
if (mod?.default) {
|
|
35
|
+
this.setFetchHandler(mod.default);
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
31
40
|
isDev() {
|
|
32
41
|
return true;
|
|
33
42
|
}
|
|
@@ -82,24 +91,21 @@ class AstroServerApp extends BaseApp {
|
|
|
82
91
|
});
|
|
83
92
|
return pipeline;
|
|
84
93
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Handle a request.
|
|
96
|
+
* @returns The return value indicates whether or not the request was handled
|
|
97
|
+
* by this handler. If the result is not `true`, then the request has not
|
|
98
|
+
* been handled yet and other handlers can be run.
|
|
99
|
+
*/
|
|
89
100
|
async handleRequest({
|
|
90
101
|
controller,
|
|
91
102
|
incomingRequest,
|
|
92
103
|
incomingResponse,
|
|
93
|
-
isHttps
|
|
104
|
+
isHttps,
|
|
105
|
+
prerenderOnly
|
|
94
106
|
}) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
getFirstForwardedValue(incomingRequest.headers["x-forwarded-host"]),
|
|
98
|
-
getFirstForwardedValue(incomingRequest.headers["x-forwarded-port"]),
|
|
99
|
-
this.manifest.allowedDomains
|
|
100
|
-
);
|
|
101
|
-
const protocol = validated.protocol ?? (isHttps ? "https" : "http");
|
|
102
|
-
const host = validated.host ?? incomingRequest.headers[":authority"] ?? incomingRequest.headers.host;
|
|
107
|
+
const protocol = isHttps ? "https" : "http";
|
|
108
|
+
const host = incomingRequest.headers[":authority"] ?? incomingRequest.headers.host;
|
|
103
109
|
const origin = `${protocol}://${host}`;
|
|
104
110
|
const url = new URL(origin + incomingRequest.url);
|
|
105
111
|
let pathname;
|
|
@@ -108,33 +114,40 @@ class AstroServerApp extends BaseApp {
|
|
|
108
114
|
} else {
|
|
109
115
|
pathname = decodeURI(url.pathname);
|
|
110
116
|
}
|
|
111
|
-
if (this.manifest.trailingSlash === "never" && pathname === "/" && this.manifest.base !== "/") {
|
|
112
|
-
pathname = "";
|
|
113
|
-
}
|
|
114
117
|
url.pathname = removeTrailingForwardSlash(this.manifest.base) + url.pathname;
|
|
115
118
|
if (url.pathname.endsWith("/") && !shouldAppendForwardSlash(this.manifest.trailingSlash, this.manifest.buildFormat)) {
|
|
116
119
|
url.pathname = url.pathname.slice(0, -1);
|
|
117
120
|
}
|
|
118
|
-
let body = void 0;
|
|
119
|
-
if (!(incomingRequest.method === "GET" || incomingRequest.method === "HEAD")) {
|
|
120
|
-
let bytes = [];
|
|
121
|
-
await new Promise((resolve) => {
|
|
122
|
-
incomingRequest.on("data", (part) => {
|
|
123
|
-
bytes.push(part);
|
|
124
|
-
});
|
|
125
|
-
incomingRequest.on("end", resolve);
|
|
126
|
-
});
|
|
127
|
-
body = Buffer.concat(bytes);
|
|
128
|
-
}
|
|
129
121
|
const self = this;
|
|
122
|
+
await self.#loadFetchHandler();
|
|
123
|
+
let handled = true;
|
|
130
124
|
await runWithErrorHandling({
|
|
131
125
|
controller,
|
|
132
126
|
pathname,
|
|
133
127
|
async run() {
|
|
134
128
|
const matchedRoute = await self.devMatch(pathname);
|
|
135
129
|
if (!matchedRoute) {
|
|
130
|
+
if (prerenderOnly) {
|
|
131
|
+
handled = false;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
136
134
|
throw new Error("No route matched, and default 404 route was not found.");
|
|
137
135
|
}
|
|
136
|
+
if (prerenderOnly && !matchedRoute.routeData.prerender) {
|
|
137
|
+
handled = false;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
let body = void 0;
|
|
141
|
+
if (!(incomingRequest.method === "GET" || incomingRequest.method === "HEAD")) {
|
|
142
|
+
let bytes = [];
|
|
143
|
+
await new Promise((resolve) => {
|
|
144
|
+
incomingRequest.on("data", (part) => {
|
|
145
|
+
bytes.push(part);
|
|
146
|
+
});
|
|
147
|
+
incomingRequest.on("end", resolve);
|
|
148
|
+
});
|
|
149
|
+
body = Buffer.concat(bytes);
|
|
150
|
+
}
|
|
138
151
|
const request = createRequest({
|
|
139
152
|
url,
|
|
140
153
|
headers: incomingRequest.headers,
|
|
@@ -170,64 +183,13 @@ class AstroServerApp extends BaseApp {
|
|
|
170
183
|
return error;
|
|
171
184
|
}
|
|
172
185
|
});
|
|
186
|
+
return handled;
|
|
173
187
|
}
|
|
174
188
|
match(request, _allowPrerenderedRoutes) {
|
|
175
189
|
return super.match(request, true);
|
|
176
190
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
error,
|
|
180
|
-
status,
|
|
181
|
-
response: _response,
|
|
182
|
-
...resolvedRenderOptions
|
|
183
|
-
}) {
|
|
184
|
-
if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
const renderRoute = async (routeData) => {
|
|
188
|
-
try {
|
|
189
|
-
const preloadedComponent = await this.pipeline.getComponentByRoute(routeData);
|
|
190
|
-
const renderContext = await this.createRenderContext({
|
|
191
|
-
locals: resolvedRenderOptions.locals,
|
|
192
|
-
pipeline: this.pipeline,
|
|
193
|
-
pathname: this.getPathnameFromRequest(request),
|
|
194
|
-
skipMiddleware,
|
|
195
|
-
request,
|
|
196
|
-
routeData,
|
|
197
|
-
clientAddress: resolvedRenderOptions.clientAddress,
|
|
198
|
-
status,
|
|
199
|
-
shouldInjectCspMetaTags: !!this.manifest.csp
|
|
200
|
-
});
|
|
201
|
-
renderContext.props.error = error;
|
|
202
|
-
const response = await renderContext.render(preloadedComponent);
|
|
203
|
-
if (error) {
|
|
204
|
-
this.logger.error("router", error.stack || error.message);
|
|
205
|
-
}
|
|
206
|
-
return response;
|
|
207
|
-
} catch (_err) {
|
|
208
|
-
if (skipMiddleware === false) {
|
|
209
|
-
return this.renderError(request, {
|
|
210
|
-
...resolvedRenderOptions,
|
|
211
|
-
status: 500,
|
|
212
|
-
skipMiddleware: true,
|
|
213
|
-
error: _err
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
throw _err;
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
if (status === 404) {
|
|
220
|
-
const custom404 = getCustom404Route(this.manifestData);
|
|
221
|
-
if (custom404) {
|
|
222
|
-
return renderRoute(custom404);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
const custom500 = getCustom500Route(this.manifestData);
|
|
226
|
-
if (!custom500) {
|
|
227
|
-
throw error;
|
|
228
|
-
} else {
|
|
229
|
-
return renderRoute(custom500);
|
|
230
|
-
}
|
|
191
|
+
createErrorHandler() {
|
|
192
|
+
return new DevErrorHandler(this, { shouldInjectCspMetaTags: true });
|
|
231
193
|
}
|
|
232
194
|
logRequest({ pathname, method, statusCode, isRewrite, reqTime }) {
|
|
233
195
|
if (pathname === "/favicon.ico") {
|
|
@@ -4,5 +4,7 @@ import type { ModuleLoader } from '../core/module-loader/index.js';
|
|
|
4
4
|
import type { AstroSettings } from '../types/astro.js';
|
|
5
5
|
import type { DevServerController } from '../vite-plugin-astro-server/controller.js';
|
|
6
6
|
export default function createAstroServerApp(controller: DevServerController, settings: AstroSettings, loader: ModuleLoader, logger?: AstroLogger): Promise<{
|
|
7
|
-
handler(incomingRequest: http.IncomingMessage, incomingResponse: http.ServerResponse
|
|
7
|
+
handler(incomingRequest: http.IncomingMessage, incomingResponse: http.ServerResponse, options?: {
|
|
8
|
+
prerenderOnly?: boolean;
|
|
9
|
+
}): Promise<boolean>;
|
|
8
10
|
}>;
|
|
@@ -60,12 +60,13 @@ async function createAstroServerApp(controller, settings, loader, logger) {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
return {
|
|
63
|
-
handler(incomingRequest, incomingResponse) {
|
|
64
|
-
app.handleRequest({
|
|
63
|
+
handler(incomingRequest, incomingResponse, options) {
|
|
64
|
+
return app.handleRequest({
|
|
65
65
|
controller,
|
|
66
66
|
incomingRequest,
|
|
67
67
|
incomingResponse,
|
|
68
|
-
isHttps: loader?.isHttps() ?? false
|
|
68
|
+
isHttps: loader?.isHttps() ?? false,
|
|
69
|
+
prerenderOnly: options?.prerenderOnly
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
};
|
|
@@ -107,15 +107,21 @@ function createVitePluginAstroServer({
|
|
|
107
107
|
}
|
|
108
108
|
try {
|
|
109
109
|
const pathname = decodeURI(new URL(request.url, "http://localhost").pathname);
|
|
110
|
-
const { routes } = await prerenderHandler.environment.runner.import(
|
|
111
|
-
|
|
110
|
+
const { routes } = await prerenderHandler.environment.runner.import(
|
|
111
|
+
"virtual:astro:routes"
|
|
112
|
+
);
|
|
113
|
+
const routesList = { routes: routes.map((route) => route.routeData) };
|
|
112
114
|
const matches = matchAllRoutes(pathname, routesList);
|
|
113
115
|
if (!matches.some((route) => route.prerender)) {
|
|
114
116
|
return next();
|
|
115
117
|
}
|
|
116
|
-
localStorage.run(
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
const handled = await localStorage.run(
|
|
119
|
+
request,
|
|
120
|
+
() => prerenderHandler.handler(request, response, { prerenderOnly: true })
|
|
121
|
+
);
|
|
122
|
+
if (!handled) {
|
|
123
|
+
return next();
|
|
124
|
+
}
|
|
119
125
|
} catch (err) {
|
|
120
126
|
next(err);
|
|
121
127
|
}
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
import type * as vite from 'vite';
|
|
2
2
|
import type { AstroSettings } from '../types/astro.js';
|
|
3
|
+
/**
|
|
4
|
+
* Outcome of the route guard evaluation for a dev-server request.
|
|
5
|
+
*
|
|
6
|
+
* - **`next`** — Allow the request through to downstream middleware.
|
|
7
|
+
* - **`block`** — The file exists at the project root but outside srcDir/publicDir.
|
|
8
|
+
* Respond with a 404.
|
|
9
|
+
*/
|
|
10
|
+
export type RouteGuardDecision = {
|
|
11
|
+
action: 'next';
|
|
12
|
+
} | {
|
|
13
|
+
action: 'block';
|
|
14
|
+
pathname: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Filesystem query results needed by the route guard decision function.
|
|
18
|
+
* Callers resolve these from the real filesystem; tests can provide them directly.
|
|
19
|
+
*/
|
|
20
|
+
export interface RouteGuardFsInfo {
|
|
21
|
+
/** Whether the resolved pathname exists inside the project's `publicDir` (e.g. `public/robots.txt`). */
|
|
22
|
+
existsInPublic: boolean;
|
|
23
|
+
/** Whether the resolved pathname exists inside the project's `srcDir` (e.g. `src/pages/index.astro`). */
|
|
24
|
+
existsInSrc: boolean;
|
|
25
|
+
/** Whether the resolved pathname exists at the project root as a **file** (not a directory). Directories are allowed through because they may share names with valid page routes. */
|
|
26
|
+
existsAtRootAsFile: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Pure decision function for the route guard middleware.
|
|
30
|
+
*
|
|
31
|
+
* Determines whether a request should be blocked (file exists at project root
|
|
32
|
+
* but outside srcDir/publicDir) or allowed through. The filesystem lookups are
|
|
33
|
+
* injected via `fsInfo` so this function remains pure and unit-testable.
|
|
34
|
+
*/
|
|
35
|
+
export declare function evaluateRouteGuard(url: string, acceptHeader: string, fsInfo: RouteGuardFsInfo): RouteGuardDecision;
|
|
3
36
|
/**
|
|
4
37
|
* Middleware that prevents Vite from serving files that exist outside
|
|
5
38
|
* of srcDir and publicDir when accessed via direct URL navigation.
|
|
@@ -10,6 +10,30 @@ const VITE_INTERNAL_PREFIXES = [
|
|
|
10
10
|
"/node_modules/",
|
|
11
11
|
"/.astro/"
|
|
12
12
|
];
|
|
13
|
+
function evaluateRouteGuard(url, acceptHeader, fsInfo) {
|
|
14
|
+
if (!acceptHeader.includes("text/html")) {
|
|
15
|
+
return { action: "next" };
|
|
16
|
+
}
|
|
17
|
+
let pathname;
|
|
18
|
+
try {
|
|
19
|
+
pathname = decodeURI(new URL(url, "http://localhost").pathname);
|
|
20
|
+
} catch {
|
|
21
|
+
return { action: "next" };
|
|
22
|
+
}
|
|
23
|
+
if (VITE_INTERNAL_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
|
|
24
|
+
return { action: "next" };
|
|
25
|
+
}
|
|
26
|
+
if (url.includes("?")) {
|
|
27
|
+
return { action: "next" };
|
|
28
|
+
}
|
|
29
|
+
if (fsInfo.existsInPublic || fsInfo.existsInSrc) {
|
|
30
|
+
return { action: "next" };
|
|
31
|
+
}
|
|
32
|
+
if (fsInfo.existsAtRootAsFile) {
|
|
33
|
+
return { action: "block", pathname };
|
|
34
|
+
}
|
|
35
|
+
return { action: "next" };
|
|
36
|
+
}
|
|
13
37
|
function routeGuardMiddleware(settings) {
|
|
14
38
|
const { config } = settings;
|
|
15
39
|
return function devRouteGuard(req, res, next) {
|
|
@@ -18,41 +42,36 @@ function routeGuardMiddleware(settings) {
|
|
|
18
42
|
return next();
|
|
19
43
|
}
|
|
20
44
|
const accept = req.headers.accept || "";
|
|
21
|
-
if (!accept.includes("text/html")) {
|
|
22
|
-
return next();
|
|
23
|
-
}
|
|
24
45
|
let pathname;
|
|
25
46
|
try {
|
|
26
47
|
pathname = decodeURI(new URL(url, "http://localhost").pathname);
|
|
27
48
|
} catch {
|
|
28
49
|
return next();
|
|
29
50
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (fs.existsSync(srcFilePath)) {
|
|
42
|
-
return next();
|
|
51
|
+
const fsInfo = {
|
|
52
|
+
existsInPublic: fs.existsSync(new URL("." + pathname, config.publicDir)),
|
|
53
|
+
existsInSrc: fs.existsSync(new URL("." + pathname, config.srcDir)),
|
|
54
|
+
existsAtRootAsFile: false
|
|
55
|
+
};
|
|
56
|
+
if (accept.includes("text/html") && !url.includes("?") && !VITE_INTERNAL_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
|
|
57
|
+
try {
|
|
58
|
+
const stat = fs.statSync(new URL("." + pathname, config.root));
|
|
59
|
+
fsInfo.existsAtRootAsFile = stat.isFile();
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const html = notFoundTemplate(pathname);
|
|
63
|
+
const decision = evaluateRouteGuard(url, accept, fsInfo);
|
|
64
|
+
switch (decision.action) {
|
|
65
|
+
case "block": {
|
|
66
|
+
const html = notFoundTemplate(decision.pathname);
|
|
49
67
|
return writeHtmlResponse(res, 404, html);
|
|
50
68
|
}
|
|
51
|
-
|
|
69
|
+
case "next":
|
|
70
|
+
return next();
|
|
52
71
|
}
|
|
53
|
-
return next();
|
|
54
72
|
};
|
|
55
73
|
}
|
|
56
74
|
export {
|
|
75
|
+
evaluateRouteGuard,
|
|
57
76
|
routeGuardMiddleware
|
|
58
77
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function vitePluginDevStatus() {
|
|
2
|
+
return {
|
|
3
|
+
name: "astro:dev-status",
|
|
4
|
+
configureServer(viteServer) {
|
|
5
|
+
viteServer.middlewares.use(function devStatusHandler(req, res, next) {
|
|
6
|
+
if (req.url !== "/_astro/status") return next();
|
|
7
|
+
res.setHeader("Content-Type", "application/json");
|
|
8
|
+
res.end(JSON.stringify({ ok: true }));
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
vitePluginDevStatus
|
|
15
|
+
};
|
|
@@ -9,11 +9,20 @@ import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
|
|
|
9
9
|
const VIRTUAL_COMPONENT_METADATA = "virtual:astro:component-metadata";
|
|
10
10
|
const RESOLVED_VIRTUAL_COMPONENT_METADATA = `\0${VIRTUAL_COMPONENT_METADATA}`;
|
|
11
11
|
function configHeadVitePlugin() {
|
|
12
|
-
let
|
|
12
|
+
let environments = [];
|
|
13
|
+
function findModule(id) {
|
|
14
|
+
for (const env of environments) {
|
|
15
|
+
const mod = env.moduleGraph.getModuleById(id);
|
|
16
|
+
if (mod) return mod;
|
|
17
|
+
}
|
|
18
|
+
return void 0;
|
|
19
|
+
}
|
|
13
20
|
function invalidateComponentMetadataModule() {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
for (const env of environments) {
|
|
22
|
+
const virtualMod = env.moduleGraph.getModuleById(RESOLVED_VIRTUAL_COMPONENT_METADATA);
|
|
23
|
+
if (virtualMod) {
|
|
24
|
+
env.moduleGraph.invalidateModule(virtualMod);
|
|
25
|
+
}
|
|
17
26
|
}
|
|
18
27
|
}
|
|
19
28
|
function buildImporterGraphFromEnvironment(seed) {
|
|
@@ -23,7 +32,7 @@ function configHeadVitePlugin() {
|
|
|
23
32
|
const current = queue.pop();
|
|
24
33
|
if (collected.has(current)) continue;
|
|
25
34
|
collected.add(current);
|
|
26
|
-
const mod =
|
|
35
|
+
const mod = findModule(current);
|
|
27
36
|
for (const importer of mod?.importers ?? []) {
|
|
28
37
|
if (importer.id) {
|
|
29
38
|
queue.push(importer.id);
|
|
@@ -31,7 +40,7 @@ function configHeadVitePlugin() {
|
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
return buildImporterGraphFromModuleInfo(collected, (id) => {
|
|
34
|
-
const mod =
|
|
43
|
+
const mod = findModule(id);
|
|
35
44
|
if (!mod) return null;
|
|
36
45
|
return {
|
|
37
46
|
importers: Array.from(mod.importers).map((importer) => importer.id).filter((moduleId) => !!moduleId),
|
|
@@ -61,7 +70,10 @@ function configHeadVitePlugin() {
|
|
|
61
70
|
enforce: "pre",
|
|
62
71
|
apply: "serve",
|
|
63
72
|
configureServer(devServer) {
|
|
64
|
-
|
|
73
|
+
environments = [
|
|
74
|
+
devServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr],
|
|
75
|
+
devServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.prerender]
|
|
76
|
+
].filter((e) => !!e);
|
|
65
77
|
devServer.watcher.on("add", invalidateComponentMetadataModule);
|
|
66
78
|
devServer.watcher.on("unlink", invalidateComponentMetadataModule);
|
|
67
79
|
devServer.watcher.on("change", invalidateComponentMetadataModule);
|
|
@@ -70,19 +82,24 @@ function configHeadVitePlugin() {
|
|
|
70
82
|
if (id !== RESOLVED_VIRTUAL_COMPONENT_METADATA) {
|
|
71
83
|
return;
|
|
72
84
|
}
|
|
85
|
+
const seen = /* @__PURE__ */ new Set();
|
|
73
86
|
const componentMetadataEntries = [];
|
|
74
|
-
for (const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
for (const env of environments) {
|
|
88
|
+
for (const [moduleId, mod] of env.moduleGraph.idToModuleMap) {
|
|
89
|
+
if (seen.has(moduleId)) continue;
|
|
90
|
+
const info = this.getModuleInfo(moduleId) ?? (mod.id ? this.getModuleInfo(mod.id) : null);
|
|
91
|
+
if (!info) continue;
|
|
92
|
+
const astro = getAstroMetadata(info);
|
|
93
|
+
if (!astro) continue;
|
|
94
|
+
seen.add(moduleId);
|
|
95
|
+
componentMetadataEntries.push([
|
|
96
|
+
moduleId,
|
|
97
|
+
{
|
|
98
|
+
containsHead: astro.containsHead,
|
|
99
|
+
propagation: astro.propagation
|
|
100
|
+
}
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
86
103
|
}
|
|
87
104
|
return {
|
|
88
105
|
code: `export const componentMetadataEntries = ${JSON.stringify(componentMetadataEntries)};`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRunnableDevEnvironment } from "vite";
|
|
1
2
|
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../vite-plugin-pages/const.js";
|
|
2
3
|
import { getDevCssModuleNameFromPageVirtualModuleName } from "../vite-plugin-css/util.js";
|
|
3
4
|
import { isAstroServerEnvironment } from "../environments.js";
|
|
@@ -16,7 +17,7 @@ function hmrReload() {
|
|
|
16
17
|
enforce: "post",
|
|
17
18
|
hotUpdate: {
|
|
18
19
|
order: "post",
|
|
19
|
-
handler({ modules, server, timestamp }) {
|
|
20
|
+
handler({ modules, server, timestamp, file }) {
|
|
20
21
|
if (!isAstroServerEnvironment(this.environment)) return;
|
|
21
22
|
let hasSsrOnlyModules = false;
|
|
22
23
|
let hasSkippedStyleModules = false;
|
|
@@ -42,12 +43,33 @@ function hmrReload() {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
if (hasSsrOnlyModules) {
|
|
46
|
+
if (isRunnableDevEnvironment(this.environment)) {
|
|
47
|
+
for (const invalidated of invalidatedModules) {
|
|
48
|
+
if (invalidated.id == null) continue;
|
|
49
|
+
const runnerModule = this.environment.runner.evaluatedModules.getModuleById(
|
|
50
|
+
invalidated.id
|
|
51
|
+
);
|
|
52
|
+
if (runnerModule) {
|
|
53
|
+
this.environment.runner.evaluatedModules.invalidateModule(runnerModule);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
server.ws.send({ type: "full-reload" });
|
|
58
|
+
if (!isRunnableDevEnvironment(this.environment)) {
|
|
59
|
+
this.environment.hot.send({
|
|
60
|
+
type: "full-reload",
|
|
61
|
+
triggeredBy: file,
|
|
62
|
+
path: "*"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
46
65
|
return [];
|
|
47
66
|
}
|
|
48
67
|
if (hasSkippedStyleModules) {
|
|
49
68
|
return [];
|
|
50
69
|
}
|
|
70
|
+
if (modules.length > 0) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
51
73
|
}
|
|
52
74
|
}
|
|
53
75
|
};
|
|
@@ -4,22 +4,31 @@ function astroIntegrationsContainerPlugin({
|
|
|
4
4
|
settings,
|
|
5
5
|
logger
|
|
6
6
|
}) {
|
|
7
|
+
let server;
|
|
7
8
|
return {
|
|
8
9
|
name: "astro:integration-container",
|
|
9
|
-
async configureServer(
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
async configureServer(_server) {
|
|
11
|
+
server = _server;
|
|
12
|
+
if (_server.config.isProduction) return;
|
|
13
|
+
await runHookServerSetup({ config: settings.config, server: _server, logger });
|
|
12
14
|
},
|
|
13
15
|
async buildStart() {
|
|
14
16
|
if (settings.injectedRoutes.length === settings.resolvedInjectedRoutes.length) return;
|
|
15
17
|
settings.resolvedInjectedRoutes = await Promise.all(
|
|
16
|
-
settings.injectedRoutes.map((route) => resolveEntryPoint
|
|
18
|
+
settings.injectedRoutes.map((route) => resolveEntryPoint(route, server, this))
|
|
17
19
|
);
|
|
18
20
|
}
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
|
-
async function resolveEntryPoint(route) {
|
|
22
|
-
const
|
|
23
|
+
async function resolveEntryPoint(route, server, pluginContext) {
|
|
24
|
+
const entrypoint = route.entrypoint.toString();
|
|
25
|
+
let resolvedId;
|
|
26
|
+
if (server) {
|
|
27
|
+
const resolved = await server.environments.ssr.pluginContainer.resolveId(entrypoint);
|
|
28
|
+
resolvedId = resolved?.id;
|
|
29
|
+
} else {
|
|
30
|
+
resolvedId = await pluginContext.resolve(entrypoint).then((res) => res?.id).catch(() => void 0);
|
|
31
|
+
}
|
|
23
32
|
if (!resolvedId) return route;
|
|
24
33
|
const resolvedEntryPoint = new URL(`file://${normalizePath(resolvedId)}`);
|
|
25
34
|
return { ...route, resolvedEntryPoint };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
2
|
-
import { createMarkdownProcessor } from "@astrojs/markdown-remark";
|
|
3
2
|
import { safeParseFrontmatter } from "../content/utils.js";
|
|
4
3
|
const markdownContentEntryType = {
|
|
5
4
|
extensions: [".md"],
|
|
@@ -15,9 +14,13 @@ const markdownContentEntryType = {
|
|
|
15
14
|
// We need to handle propagation for Markdown because they support layouts which will bring in styles.
|
|
16
15
|
handlePropagation: true,
|
|
17
16
|
async getRenderFunction(config) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const { markdown, image } = config;
|
|
18
|
+
const processor = await markdown.processor.createRenderer({
|
|
19
|
+
image,
|
|
20
|
+
syntaxHighlight: markdown.syntaxHighlight,
|
|
21
|
+
shikiConfig: markdown.shikiConfig,
|
|
22
|
+
gfm: markdown.gfm,
|
|
23
|
+
smartypants: markdown.smartypants
|
|
21
24
|
});
|
|
22
25
|
return async function renderToString(entry) {
|
|
23
26
|
const result = await processor.render(entry.body ?? "", {
|
|
@@ -13,13 +13,12 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
13
13
|
"\\\\$&"
|
|
14
14
|
)} + '[^"]*)"', 'g');
|
|
15
15
|
let match;
|
|
16
|
-
let occurrenceCounter = 0;
|
|
17
16
|
while ((match = regex.exec(html)) !== null) {
|
|
18
|
-
const
|
|
19
|
-
const imageProps = JSON.parse(match[1].replace(/"/g, '"').replace(/'/g, "'"));
|
|
17
|
+
const imageProps = JSON.parse(match[1].replace(/&(?:#x22|quot);/g, '"').replace(/&(?:#x27|apos);/g, "'"));
|
|
20
18
|
const { src, ...props } = imageProps;
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
// Key on the decoded src so it lines up with the lookup in updateImageReferences,
|
|
20
|
+
// which JSON-parses the attribute too (so its key uses the decoded path).
|
|
21
|
+
imageSources[src + '_' + imageProps.index] = await getImage({src: Astro__${entry.safeName}, ...props});
|
|
23
22
|
}
|
|
24
23
|
}`;
|
|
25
24
|
}).join("\n")}
|
|
@@ -31,12 +30,9 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
31
30
|
"\\\\$&"
|
|
32
31
|
)} + '[^"]*)"', 'g');
|
|
33
32
|
let match;
|
|
34
|
-
let occurrenceCounter = 0;
|
|
35
33
|
while ((match = regex.exec(html)) !== null) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
imageSources[matchKey] = await getImage(props);
|
|
39
|
-
occurrenceCounter++;
|
|
34
|
+
const props = JSON.parse(match[1].replace(/&(?:#x22|quot);/g, '"').replace(/&(?:#x27|apos);/g, "'"));
|
|
35
|
+
imageSources[props.src + '_' + props.index] = await getImage(props);
|
|
40
36
|
}
|
|
41
37
|
}`;
|
|
42
38
|
}).join("\n")}
|
|
@@ -47,7 +43,9 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
47
43
|
const imageSources = await images(html);
|
|
48
44
|
|
|
49
45
|
return html.replaceAll(/__ASTRO_IMAGE_="([^"]+)"/gm, (full, imagePath) => {
|
|
50
|
-
|
|
46
|
+
// Markdown processors disagree on character-reference style \u2014 remark emits
|
|
47
|
+
// \`"\`/\`'\`, satteri emits \`"\`/\`'\`. Decode both before JSON.parse.
|
|
48
|
+
const decodedImagePath = JSON.parse(imagePath.replace(/&(?:#x22|quot);/g, '"').replace(/&(?:#x27|apos);/g, "'"));
|
|
51
49
|
|
|
52
50
|
// Use the 'index' property for each image occurrence
|
|
53
51
|
const srcKey = decodedImagePath.src + '_' + decodedImagePath.index;
|