astro 3.3.2 → 3.3.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.
@@ -86,7 +86,7 @@ function assets({
86
86
  },
87
87
  // In build, rewrite paths to ESM imported images in code to their final location
88
88
  async renderChunk(code) {
89
- const assetUrlRE = /__ASTRO_ASSET_IMAGE__([a-z\d]{8})__(?:_(.*?)__)?/g;
89
+ const assetUrlRE = /__ASTRO_ASSET_IMAGE__([\w$]{8})__(?:_(.*?)__)?/g;
90
90
  let match;
91
91
  let s;
92
92
  while (match = assetUrlRE.exec(code)) {
@@ -583,7 +583,11 @@ ${message}`
583
583
  ...inheritedFlags,
584
584
  ...installCommand.dependencies
585
585
  ],
586
- { cwd }
586
+ {
587
+ cwd,
588
+ // reset NODE_ENV to ensure install command run in dev mode
589
+ env: { NODE_ENV: void 0 }
590
+ }
587
591
  );
588
592
  spinner.succeed();
589
593
  return 1 /* updated */;
@@ -8,6 +8,10 @@ export interface RenderErrorOptions {
8
8
  routeData?: RouteData;
9
9
  response?: Response;
10
10
  status: 404 | 500;
11
+ /**
12
+ * Whether to skip onRequest() while rendering the error page. Defaults to false.
13
+ */
14
+ skipMiddleware?: boolean;
11
15
  }
12
16
  export declare class App {
13
17
  #private;
@@ -208,7 +208,7 @@ class App {
208
208
  * If it is a known error code, try sending the according page (e.g. 404.astro / 500.astro).
209
209
  * This also handles pre-rendered /404 or /500 routes
210
210
  */
211
- async #renderError(request, { status, response: originalResponse }) {
211
+ async #renderError(request, { status, response: originalResponse, skipMiddleware = false }) {
212
212
  const errorRouteData = matchRoute("/" + status, this.#manifestData);
213
213
  const url = new URL(request.url);
214
214
  if (errorRouteData) {
@@ -232,12 +232,22 @@ class App {
232
232
  status
233
233
  );
234
234
  const page = await mod.page();
235
- if (mod.onRequest) {
235
+ if (skipMiddleware === false && mod.onRequest) {
236
236
  this.#pipeline.setMiddlewareFunction(mod.onRequest);
237
237
  }
238
+ if (skipMiddleware) {
239
+ this.#pipeline.unsetMiddlewareFunction();
240
+ }
238
241
  const response2 = await this.#pipeline.renderRoute(newRenderContext, page);
239
242
  return this.#mergeResponses(response2, originalResponse);
240
243
  } catch {
244
+ if (skipMiddleware === false && mod.onRequest) {
245
+ return this.#renderError(request, {
246
+ status,
247
+ response: originalResponse,
248
+ skipMiddleware: true
249
+ });
250
+ }
241
251
  }
242
252
  }
243
253
  const response = this.#mergeResponses(new Response(null, { status }), originalResponse);
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "3.3.2";
1
+ const ASTRO_VERSION = "3.3.3";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -20,7 +20,7 @@ async function dev(inlineConfig) {
20
20
  base: restart.container.settings.config.base
21
21
  })
22
22
  );
23
- const currentVersion = "3.3.2";
23
+ const currentVersion = "3.3.3";
24
24
  if (currentVersion.includes("-")) {
25
25
  logger.warn(null, msg.prerelease({ currentVersion }));
26
26
  }
@@ -50,7 +50,7 @@ function serverStart({
50
50
  base,
51
51
  isRestart = false
52
52
  }) {
53
- const version = "3.3.2";
53
+ const version = "3.3.3";
54
54
  const localPrefix = `${dim("\u2503")} Local `;
55
55
  const networkPrefix = `${dim("\u2503")} Network `;
56
56
  const emptyPrefix = " ".repeat(11);
@@ -235,7 +235,7 @@ function printHelp({
235
235
  message.push(
236
236
  linebreak(),
237
237
  ` ${bgGreen(black(` ${commandName} `))} ${green(
238
- `v${"3.3.2"}`
238
+ `v${"3.3.3"}`
239
239
  )} ${headline}`
240
240
  );
241
241
  }
@@ -25,6 +25,10 @@ export declare class Pipeline {
25
25
  * A middleware function that will be called before each request.
26
26
  */
27
27
  setMiddlewareFunction(onRequest: MiddlewareEndpointHandler): void;
28
+ /**
29
+ * Removes the current middleware function. Subsequent requests won't trigger any middleware.
30
+ */
31
+ unsetMiddlewareFunction(): void;
28
32
  /**
29
33
  * Returns the current environment
30
34
  */
@@ -33,6 +33,12 @@ class Pipeline {
33
33
  setMiddlewareFunction(onRequest) {
34
34
  this.#onRequest = onRequest;
35
35
  }
36
+ /**
37
+ * Removes the current middleware function. Subsequent requests won't trigger any middleware.
38
+ */
39
+ unsetMiddlewareFunction() {
40
+ this.#onRequest = void 0;
41
+ }
36
42
  /**
37
43
  * Returns the current environment
38
44
  */
@@ -26,6 +26,7 @@ const announce = () => {
26
26
  );
27
27
  };
28
28
  const PERSIST_ATTR = "data-astro-transition-persist";
29
+ const VITE_ID = "data-vite-dev-id";
29
30
  let parser;
30
31
  let currentHistoryIndex = 0;
31
32
  if (inBrowser) {
@@ -142,6 +143,8 @@ const updateHistoryAndScrollPosition = (toLocation, replace, intraPage) => {
142
143
  async function updateDOM(newDocument, toLocation, options, popState, fallback) {
143
144
  const persistedHeadElement = (el) => {
144
145
  const id = el.getAttribute(PERSIST_ATTR);
146
+ if (id === "")
147
+ return void 0;
145
148
  const newEl = id && newDocument.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
146
149
  if (newEl) {
147
150
  return newEl;
@@ -154,7 +157,7 @@ async function updateDOM(newDocument, toLocation, options, popState, fallback) {
154
157
  };
155
158
  const saveFocus = () => {
156
159
  const activeElement = document.activeElement;
157
- if (activeElement?.closest("[data-astro-transition-persist]")) {
160
+ if (activeElement?.closest(`[${PERSIST_ATTR}]`)) {
158
161
  if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) {
159
162
  const start = activeElement.selectionStart;
160
163
  const end = activeElement.selectionEnd;
@@ -198,7 +201,7 @@ async function updateDOM(newDocument, toLocation, options, popState, fallback) {
198
201
  const newEl = persistedHeadElement(el);
199
202
  if (newEl) {
200
203
  newEl.remove();
201
- } else {
204
+ } else if (newEl === null) {
202
205
  el.remove();
203
206
  }
204
207
  }
@@ -274,6 +277,8 @@ async function transition(direction, toLocation, options, popState) {
274
277
  location.href = href;
275
278
  return;
276
279
  }
280
+ if (import.meta.env.DEV)
281
+ await prepareForClientOnlyComponents(newDocument, toLocation);
277
282
  if (!popState) {
278
283
  history.replaceState({ ...history.state, scrollX, scrollY }, "");
279
284
  }
@@ -359,6 +364,41 @@ if (inBrowser) {
359
364
  markScriptsExec();
360
365
  }
361
366
  }
367
+ async function prepareForClientOnlyComponents(newDocument, toLocation) {
368
+ if (newDocument.body.querySelector(`astro-island[client='only']`)) {
369
+ const nextPage = document.createElement("iframe");
370
+ nextPage.setAttribute("src", toLocation.href);
371
+ nextPage.style.display = "none";
372
+ document.body.append(nextPage);
373
+ await hydrationDone(nextPage);
374
+ const nextHead = nextPage.contentDocument?.head;
375
+ if (nextHead) {
376
+ document.head.querySelectorAll(`style[${PERSIST_ATTR}=""]`).forEach((s) => s.removeAttribute(PERSIST_ATTR));
377
+ const viteIds = [...nextHead.querySelectorAll(`style[${VITE_ID}]`)].map(
378
+ (style) => style.getAttribute(VITE_ID)
379
+ );
380
+ viteIds.forEach((id) => {
381
+ const style = document.head.querySelector(`style[${VITE_ID}="${id}"]`);
382
+ if (style && !newDocument.head.querySelector(`style[${VITE_ID}="${id}"]`)) {
383
+ style.setAttribute(PERSIST_ATTR, "");
384
+ }
385
+ });
386
+ }
387
+ async function hydrationDone(loadingPage) {
388
+ await new Promise(
389
+ (r) => loadingPage.contentWindow?.addEventListener("load", r, { once: true })
390
+ );
391
+ return new Promise(async (r) => {
392
+ for (let count = 0; count <= 20; ++count) {
393
+ if (!loadingPage.contentDocument.body.querySelector("astro-island[ssr]"))
394
+ break;
395
+ await new Promise((r2) => setTimeout(r2, 50));
396
+ }
397
+ r();
398
+ });
399
+ }
400
+ }
401
+ }
362
402
  export {
363
403
  navigate,
364
404
  supportsViewTransitions,
@@ -1,3 +1,4 @@
1
+ import { slash } from "@astrojs/internal-helpers/path";
1
2
  import { fileURLToPath } from "node:url";
2
3
  import {
3
4
  cachedCompilation,
@@ -55,7 +56,7 @@ async function handleHotUpdate(ctx, { config, logger, compile, source }) {
55
56
  }
56
57
  }
57
58
  const mods = [...filtered].filter((m) => !m.url.endsWith("="));
58
- const file = ctx.file.replace(config.root.pathname, "/");
59
+ const file = ctx.file.replace(slash(fileURLToPath(config.root)), "/");
59
60
  if (isStyleOnlyChange) {
60
61
  logger.info("astro", msg.hmr({ file, style: true }));
61
62
  return mods.filter((mod) => mod.id !== ctx.file && !mod.id?.endsWith(".ts"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "3.3.2",
3
+ "version": "3.3.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",