astro 3.2.0 → 3.2.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.
@@ -1967,7 +1967,7 @@ export interface SSRMetadata {
1967
1967
  hasRenderedHead: boolean;
1968
1968
  headInTree: boolean;
1969
1969
  extraHead: string[];
1970
- propagators: Map<AstroComponentFactory, AstroComponentInstance>;
1970
+ propagators: Set<AstroComponentInstance>;
1971
1971
  }
1972
1972
  export interface PreviewServer {
1973
1973
  host?: string;
@@ -1,4 +1,4 @@
1
- import type { APIRoute } from '../@types/astro.js';
1
+ import type { APIRoute } from '../../@types/astro.js';
2
2
  /**
3
3
  * Endpoint used in dev and SSR to serve optimized images by the base image services
4
4
  */
@@ -1,7 +1,7 @@
1
1
  import { isRemotePath } from "@astrojs/internal-helpers/path";
2
2
  import mime from "mime/lite.js";
3
- import { getConfiguredImageService, isRemoteAllowed } from "./internal.js";
4
- import { etag } from "./utils/etag.js";
3
+ import { getConfiguredImageService, isRemoteAllowed } from "../internal.js";
4
+ import { etag } from "../utils/etag.js";
5
5
  import { imageConfig } from "astro:assets";
6
6
  async function loadRemoteImage(src) {
7
7
  try {
@@ -0,0 +1,5 @@
1
+ import type { APIRoute } from '../../@types/astro.js';
2
+ /**
3
+ * Endpoint used in dev and SSR to serve optimized images by the base image services
4
+ */
5
+ export declare const GET: APIRoute;
@@ -0,0 +1,68 @@
1
+ import { isRemotePath, removeQueryString } from "@astrojs/internal-helpers/path";
2
+ import { readFile } from "fs/promises";
3
+ import mime from "mime/lite.js";
4
+ import { getConfiguredImageService, isRemoteAllowed } from "../internal.js";
5
+ import { etag } from "../utils/etag.js";
6
+ import { assetsDir, imageConfig } from "astro:assets";
7
+ async function loadLocalImage(src, url) {
8
+ const filePath = import.meta.env.DEV ? removeQueryString(src.slice("/@fs".length)) : new URL("." + src, assetsDir);
9
+ let buffer = void 0;
10
+ try {
11
+ buffer = await readFile(filePath);
12
+ } catch (e) {
13
+ const sourceUrl = new URL(src, url.origin);
14
+ buffer = await loadRemoteImage(sourceUrl);
15
+ }
16
+ return buffer;
17
+ }
18
+ async function loadRemoteImage(src) {
19
+ try {
20
+ const res = await fetch(src);
21
+ if (!res.ok) {
22
+ return void 0;
23
+ }
24
+ return Buffer.from(await res.arrayBuffer());
25
+ } catch (err) {
26
+ return void 0;
27
+ }
28
+ }
29
+ const GET = async ({ request }) => {
30
+ try {
31
+ const imageService = await getConfiguredImageService();
32
+ if (!("transform" in imageService)) {
33
+ throw new Error("Configured image service is not a local service");
34
+ }
35
+ const url = new URL(request.url);
36
+ const transform = await imageService.parseURL(url, imageConfig);
37
+ if (!transform?.src) {
38
+ throw new Error("Incorrect transform returned by `parseURL`");
39
+ }
40
+ let inputBuffer = void 0;
41
+ if (isRemotePath(transform.src)) {
42
+ if (isRemoteAllowed(transform.src, imageConfig) === false) {
43
+ return new Response("Forbidden", { status: 403 });
44
+ }
45
+ inputBuffer = await loadRemoteImage(new URL(transform.src));
46
+ } else {
47
+ inputBuffer = await loadLocalImage(transform.src, url);
48
+ }
49
+ if (!inputBuffer) {
50
+ return new Response("Not Found", { status: 404 });
51
+ }
52
+ const { data, format } = await imageService.transform(inputBuffer, transform, imageConfig);
53
+ return new Response(data, {
54
+ status: 200,
55
+ headers: {
56
+ "Content-Type": mime.getType(format) ?? `image/${format}`,
57
+ "Cache-Control": "public, max-age=31536000",
58
+ ETag: etag(data.toString()),
59
+ Date: (/* @__PURE__ */ new Date()).toUTCString()
60
+ }
61
+ });
62
+ } catch (err) {
63
+ return new Response(`Server Error: ${err}`, { status: 500 });
64
+ }
65
+ };
66
+ export {
67
+ GET
68
+ };
@@ -1,7 +1,7 @@
1
1
  import type { AstroConfig, AstroSettings } from '../@types/astro.js';
2
2
  import { type ImageService } from './services/service.js';
3
3
  import type { GetImageResult, ImageMetadata, UnresolvedImageTransform } from './types.js';
4
- export declare function injectImageEndpoint(settings: AstroSettings): AstroSettings;
4
+ export declare function injectImageEndpoint(settings: AstroSettings, mode: 'dev' | 'build'): AstroSettings;
5
5
  export declare function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata;
6
6
  export declare function isRemoteImage(src: ImageMetadata | string): src is string;
7
7
  export declare function isRemoteAllowed(src: string, { domains, remotePatterns, }: Partial<Pick<AstroConfig['image'], 'domains' | 'remotePatterns'>>): boolean;
@@ -2,8 +2,8 @@ import { isRemotePath } from "@astrojs/internal-helpers/path";
2
2
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
3
3
  import { isLocalService } from "./services/service.js";
4
4
  import { matchHostname, matchPattern } from "./utils/remotePattern.js";
5
- function injectImageEndpoint(settings) {
6
- const endpointEntrypoint = settings.config.image.endpoint ?? "astro/assets/image-endpoint";
5
+ function injectImageEndpoint(settings, mode) {
6
+ const endpointEntrypoint = settings.config.image.endpoint ?? (mode === "dev" ? "astro/assets/endpoint/node" : "astro/assets/endpoint/generic");
7
7
  settings.injectedRoutes.push({
8
8
  pattern: "/_image",
9
9
  entryPoint: endpointEntrypoint,
@@ -8,6 +8,7 @@ import {
8
8
  prependForwardSlash,
9
9
  removeQueryString
10
10
  } from "../core/path.js";
11
+ import { isServerLikeOutput } from "../prerender/utils.js";
11
12
  import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from "./consts.js";
12
13
  import { emitESMImage } from "./utils/emitAsset.js";
13
14
  import { hashTransform, propsToFilename } from "./utils/transformToPath.js";
@@ -48,6 +49,11 @@ function assets({
48
49
  export { default as Image } from "astro/components/Image.astro";
49
50
 
50
51
  export const imageConfig = ${JSON.stringify(settings.config.image)};
52
+ export const assetsDir = new URL(${JSON.stringify(
53
+ new URL(
54
+ isServerLikeOutput(settings.config) ? settings.config.build.client : settings.config.outDir
55
+ )
56
+ )});
51
57
  export const getImage = async (options) => await getImageInternal(options, imageConfig);
52
58
  `;
53
59
  }
@@ -49,7 +49,7 @@ function astroContentAssetPropagationPlugin({
49
49
  if (!devModuleLoader.getModuleById(basePath)?.ssrModule) {
50
50
  await devModuleLoader.import(basePath);
51
51
  }
52
- const { stylesMap, urls } = await getStylesForURL(
52
+ const { styles, urls } = await getStylesForURL(
53
53
  pathToFileURL(basePath),
54
54
  devModuleLoader,
55
55
  "development"
@@ -60,7 +60,7 @@ function astroContentAssetPropagationPlugin({
60
60
  devModuleLoader
61
61
  );
62
62
  stringifiedLinks = JSON.stringify([...urls]);
63
- stringifiedStyles = JSON.stringify([...stylesMap.values()]);
63
+ stringifiedStyles = JSON.stringify(styles.map((s) => s.content));
64
64
  stringifiedScripts = JSON.stringify([...hoistedScripts]);
65
65
  } else {
66
66
  stringifiedLinks = JSON.stringify(LINKS_PLACEHOLDER);
@@ -68,7 +68,7 @@ class AstroBuilder {
68
68
  logger
69
69
  });
70
70
  if (isServerLikeOutput(this.settings.config)) {
71
- this.settings = injectImageEndpoint(this.settings);
71
+ this.settings = injectImageEndpoint(this.settings, "build");
72
72
  }
73
73
  this.manifest = createRouteManifest({ settings: this.settings }, this.logger);
74
74
  const viteConfig = await createVite(
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "3.2.0";
1
+ const ASTRO_VERSION = "3.2.2";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -23,7 +23,7 @@ async function createContainer({
23
23
  logger,
24
24
  isRestart
25
25
  });
26
- settings = injectImageEndpoint(settings);
26
+ settings = injectImageEndpoint(settings, "dev");
27
27
  const {
28
28
  base,
29
29
  server: { host, headers, open: shouldOpen }
@@ -20,7 +20,7 @@ async function dev(inlineConfig) {
20
20
  base: restart.container.settings.config.base
21
21
  })
22
22
  );
23
- const currentVersion = "3.2.0";
23
+ const currentVersion = "3.2.2";
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.2.0";
53
+ const version = "3.2.2";
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.2.0"}`
238
+ `v${"3.2.2"}`
239
239
  )} ${headline}`
240
240
  );
241
241
  }
@@ -156,7 +156,7 @@ function createResult(args) {
156
156
  hasDirectives: /* @__PURE__ */ new Set(),
157
157
  headInTree: false,
158
158
  extraHead: [],
159
- propagators: /* @__PURE__ */ new Map()
159
+ propagators: /* @__PURE__ */ new Set()
160
160
  }
161
161
  };
162
162
  return result;
@@ -1,36 +1,2 @@
1
1
  if (import.meta.hot) {
2
- const injectedStyles = getInjectedStyles();
3
- const mo = new MutationObserver((records) => {
4
- for (const record of records) {
5
- for (const node of record.addedNodes) {
6
- if (isViteInjectedStyle(node)) {
7
- injectedStyles.get(node.getAttribute("data-vite-dev-id"))?.remove();
8
- }
9
- }
10
- }
11
- });
12
- mo.observe(document.documentElement, { subtree: true, childList: true });
13
- import.meta.hot.on("vite:beforeUpdate", async (payload) => {
14
- for (const file of payload.updates) {
15
- if (file.acceptedPath.includes("vue&type=style")) {
16
- const link = document.querySelector(`link[href="${file.acceptedPath}"]`);
17
- if (link) {
18
- link.replaceWith(link.cloneNode(true));
19
- }
20
- }
21
- }
22
- });
23
- }
24
- function getInjectedStyles() {
25
- const injectedStyles = /* @__PURE__ */ new Map();
26
- document.querySelectorAll("style[data-astro-dev-id]").forEach((el) => {
27
- injectedStyles.set(el.getAttribute("data-astro-dev-id"), el);
28
- });
29
- return injectedStyles;
30
- }
31
- function isStyle(node) {
32
- return node.nodeType === node.ELEMENT_NODE && node.tagName.toLowerCase() === "style";
33
- }
34
- function isViteInjectedStyle(node) {
35
- return isStyle(node) && !!node.getAttribute("data-vite-dev-id");
36
2
  }
@@ -34,13 +34,22 @@
34
34
  document.addEventListener("astro:after-swap", this.unmount, { once: true });
35
35
  }
36
36
  connectedCallback() {
37
- if (!this.hasAttribute("await-children") || this.firstChild) {
37
+ if (!this.hasAttribute("await-children") || document.readyState === "interactive" || document.readyState === "complete") {
38
38
  this.childrenConnectedCallback();
39
39
  } else {
40
- new MutationObserver((_, mo) => {
40
+ const onConnected = () => {
41
+ document.removeEventListener("DOMContentLoaded", onConnected);
41
42
  mo.disconnect();
42
- setTimeout(() => this.childrenConnectedCallback(), 0);
43
- }).observe(this, { childList: true });
43
+ this.childrenConnectedCallback();
44
+ };
45
+ const mo = new MutationObserver(() => {
46
+ if (this.lastChild?.nodeType === Node.COMMENT_NODE && this.lastChild.nodeValue === "astro:end") {
47
+ this.lastChild.remove();
48
+ onConnected();
49
+ }
50
+ });
51
+ mo.observe(this, { childList: true });
52
+ document.addEventListener("DOMContentLoaded", onConnected);
44
53
  }
45
54
  }
46
55
  async childrenConnectedCallback() {
@@ -3,5 +3,5 @@
3
3
  * Do not edit this directly, but instead edit that file and rerun the prebuild
4
4
  * to generate this file.
5
5
  */
6
- declare const _default: "(()=>{var b=Object.defineProperty;var f=(a,s,i)=>s in a?b(a,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):a[s]=i;var d=(a,s,i)=>(f(a,typeof s!=\"symbol\"?s+\"\":s,i),i);var u;{let a={0:t=>m(t),1:t=>i(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(i(t)),5:t=>new Set(i(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t)},s=t=>{let[e,r]=t;return e in a?a[e](r):void 0},i=t=>t.map(s),m=t=>typeof t!=\"object\"||t===null?t:Object.fromEntries(Object.entries(t).map(([e,r])=>[e,s(r)]));customElements.get(\"astro-island\")||customElements.define(\"astro-island\",(u=class extends HTMLElement{constructor(){super(...arguments);d(this,\"Component\");d(this,\"hydrator\");d(this,\"hydrate\",async()=>{var l;if(!this.hydrator||!this.isConnected)return;let e=(l=this.parentElement)==null?void 0:l.closest(\"astro-island[ssr]\");if(e){e.addEventListener(\"astro:hydrate\",this.hydrate,{once:!0});return}let r=this.querySelectorAll(\"astro-slot\"),c={},h=this.querySelectorAll(\"template[data-astro-template]\");for(let n of h){let o=n.closest(this.tagName);o!=null&&o.isSameNode(this)&&(c[n.getAttribute(\"data-astro-template\")||\"default\"]=n.innerHTML,n.remove())}for(let n of r){let o=n.closest(this.tagName);o!=null&&o.isSameNode(this)&&(c[n.getAttribute(\"name\")||\"default\"]=n.innerHTML)}let p;try{p=this.hasAttribute(\"props\")?m(JSON.parse(this.getAttribute(\"props\"))):{}}catch(n){let o=this.getAttribute(\"component-url\")||\"<unknown>\",y=this.getAttribute(\"component-export\");throw y&&(o+=` (export ${y})`),console.error(`[hydrate] Error parsing props for component ${o}`,this.getAttribute(\"props\"),n),n}await this.hydrator(this)(this.Component,p,c,{client:this.getAttribute(\"client\")}),this.removeAttribute(\"ssr\"),this.dispatchEvent(new CustomEvent(\"astro:hydrate\"))});d(this,\"unmount\",()=>{this.isConnected||this.dispatchEvent(new CustomEvent(\"astro:unmount\"))})}disconnectedCallback(){document.removeEventListener(\"astro:after-swap\",this.unmount),document.addEventListener(\"astro:after-swap\",this.unmount,{once:!0})}connectedCallback(){!this.hasAttribute(\"await-children\")||this.firstChild?this.childrenConnectedCallback():new MutationObserver((e,r)=>{r.disconnect(),setTimeout(()=>this.childrenConnectedCallback(),0)}).observe(this,{childList:!0})}async childrenConnectedCallback(){let e=this.getAttribute(\"before-hydration-url\");e&&await import(e),this.start()}start(){let e=JSON.parse(this.getAttribute(\"opts\")),r=this.getAttribute(\"client\");if(Astro[r]===void 0){window.addEventListener(`astro:${r}`,()=>this.start(),{once:!0});return}Astro[r](async()=>{let c=this.getAttribute(\"renderer-url\"),[h,{default:p}]=await Promise.all([import(this.getAttribute(\"component-url\")),c?import(c):()=>()=>{}]),l=this.getAttribute(\"component-export\")||\"default\";if(!l.includes(\".\"))this.Component=h[l];else{this.Component=h;for(let n of l.split(\".\"))this.Component=this.Component[n]}return this.hydrator=p,this.hydrate},e,this)}attributeChangedCallback(){this.hydrate()}},d(u,\"observedAttributes\",[\"props\"]),u))}})();";
6
+ declare const _default: "(()=>{var b=Object.defineProperty;var f=(c,o,i)=>o in c?b(c,o,{enumerable:!0,configurable:!0,writable:!0,value:i}):c[o]=i;var l=(c,o,i)=>(f(c,typeof o!=\"symbol\"?o+\"\":o,i),i);var p;{let c={0:t=>m(t),1:t=>i(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(i(t)),5:t=>new Set(i(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t)},o=t=>{let[e,r]=t;return e in c?c[e](r):void 0},i=t=>t.map(o),m=t=>typeof t!=\"object\"||t===null?t:Object.fromEntries(Object.entries(t).map(([e,r])=>[e,o(r)]));customElements.get(\"astro-island\")||customElements.define(\"astro-island\",(p=class extends HTMLElement{constructor(){super(...arguments);l(this,\"Component\");l(this,\"hydrator\");l(this,\"hydrate\",async()=>{var d;if(!this.hydrator||!this.isConnected)return;let e=(d=this.parentElement)==null?void 0:d.closest(\"astro-island[ssr]\");if(e){e.addEventListener(\"astro:hydrate\",this.hydrate,{once:!0});return}let r=this.querySelectorAll(\"astro-slot\"),a={},h=this.querySelectorAll(\"template[data-astro-template]\");for(let n of h){let s=n.closest(this.tagName);s!=null&&s.isSameNode(this)&&(a[n.getAttribute(\"data-astro-template\")||\"default\"]=n.innerHTML,n.remove())}for(let n of r){let s=n.closest(this.tagName);s!=null&&s.isSameNode(this)&&(a[n.getAttribute(\"name\")||\"default\"]=n.innerHTML)}let u;try{u=this.hasAttribute(\"props\")?m(JSON.parse(this.getAttribute(\"props\"))):{}}catch(n){let s=this.getAttribute(\"component-url\")||\"<unknown>\",y=this.getAttribute(\"component-export\");throw y&&(s+=` (export ${y})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute(\"props\"),n),n}await this.hydrator(this)(this.Component,u,a,{client:this.getAttribute(\"client\")}),this.removeAttribute(\"ssr\"),this.dispatchEvent(new CustomEvent(\"astro:hydrate\"))});l(this,\"unmount\",()=>{this.isConnected||this.dispatchEvent(new CustomEvent(\"astro:unmount\"))})}disconnectedCallback(){document.removeEventListener(\"astro:after-swap\",this.unmount),document.addEventListener(\"astro:after-swap\",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute(\"await-children\")||document.readyState===\"interactive\"||document.readyState===\"complete\")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener(\"DOMContentLoaded\",e),r.disconnect(),this.childrenConnectedCallback()},r=new MutationObserver(()=>{var a;((a=this.lastChild)==null?void 0:a.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue===\"astro:end\"&&(this.lastChild.remove(),e())});r.observe(this,{childList:!0}),document.addEventListener(\"DOMContentLoaded\",e)}}async childrenConnectedCallback(){let e=this.getAttribute(\"before-hydration-url\");e&&await import(e),this.start()}start(){let e=JSON.parse(this.getAttribute(\"opts\")),r=this.getAttribute(\"client\");if(Astro[r]===void 0){window.addEventListener(`astro:${r}`,()=>this.start(),{once:!0});return}Astro[r](async()=>{let a=this.getAttribute(\"renderer-url\"),[h,{default:u}]=await Promise.all([import(this.getAttribute(\"component-url\")),a?import(a):()=>()=>{}]),d=this.getAttribute(\"component-export\")||\"default\";if(!d.includes(\".\"))this.Component=h[d];else{this.Component=h;for(let n of d.split(\".\"))this.Component=this.Component[n]}return this.hydrator=u,this.hydrate},e,this)}attributeChangedCallback(){this.hydrate()}},l(p,\"observedAttributes\",[\"props\"]),p))}})();";
7
7
  export default _default;
@@ -1,4 +1,4 @@
1
- var astro_island_prebuilt_default = `(()=>{var b=Object.defineProperty;var f=(a,s,i)=>s in a?b(a,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):a[s]=i;var d=(a,s,i)=>(f(a,typeof s!="symbol"?s+"":s,i),i);var u;{let a={0:t=>m(t),1:t=>i(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(i(t)),5:t=>new Set(i(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t)},s=t=>{let[e,r]=t;return e in a?a[e](r):void 0},i=t=>t.map(s),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([e,r])=>[e,s(r)]));customElements.get("astro-island")||customElements.define("astro-island",(u=class extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var l;if(!this.hydrator||!this.isConnected)return;let e=(l=this.parentElement)==null?void 0:l.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let r=this.querySelectorAll("astro-slot"),c={},h=this.querySelectorAll("template[data-astro-template]");for(let n of h){let o=n.closest(this.tagName);o!=null&&o.isSameNode(this)&&(c[n.getAttribute("data-astro-template")||"default"]=n.innerHTML,n.remove())}for(let n of r){let o=n.closest(this.tagName);o!=null&&o.isSameNode(this)&&(c[n.getAttribute("name")||"default"]=n.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(n){let o=this.getAttribute("component-url")||"<unknown>",y=this.getAttribute("component-export");throw y&&(o+=\` (export \${y})\`),console.error(\`[hydrate] Error parsing props for component \${o}\`,this.getAttribute("props"),n),n}await this.hydrator(this)(this.Component,p,c,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){!this.hasAttribute("await-children")||this.firstChild?this.childrenConnectedCallback():new MutationObserver((e,r)=>{r.disconnect(),setTimeout(()=>this.childrenConnectedCallback(),0)}).observe(this,{childList:!0})}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}start(){let e=JSON.parse(this.getAttribute("opts")),r=this.getAttribute("client");if(Astro[r]===void 0){window.addEventListener(\`astro:\${r}\`,()=>this.start(),{once:!0});return}Astro[r](async()=>{let c=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),c?import(c):()=>()=>{}]),l=this.getAttribute("component-export")||"default";if(!l.includes("."))this.Component=h[l];else{this.Component=h;for(let n of l.split("."))this.Component=this.Component[n]}return this.hydrator=p,this.hydrate},e,this)}attributeChangedCallback(){this.hydrate()}},d(u,"observedAttributes",["props"]),u))}})();`;
1
+ var astro_island_prebuilt_default = `(()=>{var b=Object.defineProperty;var f=(c,o,i)=>o in c?b(c,o,{enumerable:!0,configurable:!0,writable:!0,value:i}):c[o]=i;var l=(c,o,i)=>(f(c,typeof o!="symbol"?o+"":o,i),i);var p;{let c={0:t=>m(t),1:t=>i(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(i(t)),5:t=>new Set(i(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t)},o=t=>{let[e,r]=t;return e in c?c[e](r):void 0},i=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([e,r])=>[e,o(r)]));customElements.get("astro-island")||customElements.define("astro-island",(p=class extends HTMLElement{constructor(){super(...arguments);l(this,"Component");l(this,"hydrator");l(this,"hydrate",async()=>{var d;if(!this.hydrator||!this.isConnected)return;let e=(d=this.parentElement)==null?void 0:d.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let r=this.querySelectorAll("astro-slot"),a={},h=this.querySelectorAll("template[data-astro-template]");for(let n of h){let s=n.closest(this.tagName);s!=null&&s.isSameNode(this)&&(a[n.getAttribute("data-astro-template")||"default"]=n.innerHTML,n.remove())}for(let n of r){let s=n.closest(this.tagName);s!=null&&s.isSameNode(this)&&(a[n.getAttribute("name")||"default"]=n.innerHTML)}let u;try{u=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(n){let s=this.getAttribute("component-url")||"<unknown>",y=this.getAttribute("component-export");throw y&&(s+=\` (export \${y})\`),console.error(\`[hydrate] Error parsing props for component \${s}\`,this.getAttribute("props"),n),n}await this.hydrator(this)(this.Component,u,a,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});l(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),r.disconnect(),this.childrenConnectedCallback()},r=new MutationObserver(()=>{var a;((a=this.lastChild)==null?void 0:a.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});r.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}start(){let e=JSON.parse(this.getAttribute("opts")),r=this.getAttribute("client");if(Astro[r]===void 0){window.addEventListener(\`astro:\${r}\`,()=>this.start(),{once:!0});return}Astro[r](async()=>{let a=this.getAttribute("renderer-url"),[h,{default:u}]=await Promise.all([import(this.getAttribute("component-url")),a?import(a):()=>()=>{}]),d=this.getAttribute("component-export")||"default";if(!d.includes("."))this.Component=h[d];else{this.Component=h;for(let n of d.split("."))this.Component=this.Component[n]}return this.hydrator=u,this.hydrate},e,this)}attributeChangedCallback(){this.hydrate()}},l(p,"observedAttributes",["props"]),p))}})();`;
2
2
  export {
3
3
  astro_island_prebuilt_default as default
4
4
  };
@@ -55,8 +55,8 @@ function validateComponentProps(props, displayName) {
55
55
  function createAstroComponentInstance(result, displayName, factory, props, slots = {}) {
56
56
  validateComponentProps(props, displayName);
57
57
  const instance = new AstroComponentInstance(result, props, slots, factory);
58
- if (isAPropagatingComponent(result, factory) && !result._metadata.propagators.has(factory)) {
59
- result._metadata.propagators.set(factory, instance);
58
+ if (isAPropagatingComponent(result, factory)) {
59
+ result._metadata.propagators.add(instance);
60
60
  }
61
61
  return instance;
62
62
  }
@@ -280,6 +280,7 @@ ${serializeProps(
280
280
  island.children = `${html ?? ""}${template}`;
281
281
  if (island.children) {
282
282
  island.props["await-children"] = "";
283
+ island.children += `<!--astro:end-->`;
283
284
  }
284
285
  return {
285
286
  render(destination) {
@@ -146,7 +146,7 @@ async function updateDOM(newDocument, toLocation, options, popState, fallback) {
146
146
  if (import.meta.env.DEV) {
147
147
  if (el.tagName === "STYLE" && el.dataset.viteDevId) {
148
148
  const devId = el.dataset.viteDevId;
149
- return newDocument.querySelector(`style[data-astro-dev-id="${devId}"]`) || // Otherwise, keep it anyways. This is client:only styles.
149
+ return newDocument.querySelector(`style[data-vite-dev-id="${devId}"]`) || // Otherwise, keep it anyways. This is client:only styles.
150
150
  noopEl;
151
151
  }
152
152
  }
@@ -200,7 +200,9 @@ async function updateDOM(newDocument, toLocation, options, popState, fallback) {
200
200
  const links = [];
201
201
  for (const el of newDocument.querySelectorAll("head link[rel=stylesheet]")) {
202
202
  if (!document.querySelector(
203
- `[${PERSIST_ATTR}="${el.getAttribute(PERSIST_ATTR)}"], link[rel=stylesheet]`
203
+ `[${PERSIST_ATTR}="${el.getAttribute(
204
+ PERSIST_ATTR
205
+ )}"], link[rel=stylesheet][href="${el.getAttribute("href")}"]`
204
206
  )) {
205
207
  const c = document.createElement("link");
206
208
  c.setAttribute("rel", "preload");
@@ -1,7 +1,13 @@
1
1
  import type { RuntimeMode } from '../@types/astro.js';
2
2
  import type { ModuleLoader } from '../core/module-loader/index.js';
3
+ interface ImportedStyle {
4
+ id: string;
5
+ url: string;
6
+ content: string;
7
+ }
3
8
  /** Given a filePath URL, crawl Vite’s module graph to find all style imports. */
4
9
  export declare function getStylesForURL(filePath: URL, loader: ModuleLoader, mode: RuntimeMode): Promise<{
5
10
  urls: Set<string>;
6
- stylesMap: Map<string, string>;
11
+ styles: ImportedStyle[];
7
12
  }>;
13
+ export {};
@@ -14,7 +14,11 @@ async function getStylesForURL(filePath, loader, mode) {
14
14
  }
15
15
  if (mode === "development" && // only inline in development
16
16
  typeof ssrModule?.default === "string") {
17
- importedStylesMap.set(importedModule.url, ssrModule.default);
17
+ importedStylesMap.set(importedModule.url, {
18
+ id: importedModule.id ?? importedModule.url,
19
+ url: importedModule.url,
20
+ content: ssrModule.default
21
+ });
18
22
  } else {
19
23
  importedCssUrls.add(importedModule.url);
20
24
  }
@@ -22,7 +26,7 @@ async function getStylesForURL(filePath, loader, mode) {
22
26
  }
23
27
  return {
24
28
  urls: importedCssUrls,
25
- stylesMap: importedStylesMap
29
+ styles: [...importedStylesMap.values()]
26
30
  };
27
31
  }
28
32
  export {
@@ -3,7 +3,7 @@ import { loadMiddleware } from "../core/middleware/loadMiddleware.js";
3
3
  import { createRenderContext, getParamsAndProps } from "../core/render/index.js";
4
4
  import { createRequest } from "../core/request.js";
5
5
  import { matchAllRoutes } from "../core/routing/index.js";
6
- import { isPage, resolveIdToUrl, viteID } from "../core/util.js";
6
+ import { isPage } from "../core/util.js";
7
7
  import { getSortedPreloadedMatches } from "../prerender/routing.js";
8
8
  import { isServerLikeOutput } from "../prerender/utils.js";
9
9
  import { PAGE_SCRIPT_ID } from "../vite-plugin-scripts/index.js";
@@ -199,13 +199,6 @@ async function getScriptsAndStyles({ pipeline, filePath }) {
199
199
  props: { type: "module", src: "/@vite/client" },
200
200
  children: ""
201
201
  });
202
- scripts.add({
203
- props: {
204
- type: "module",
205
- src: await resolveIdToUrl(moduleLoader, "astro/runtime/client/hmr.js")
206
- },
207
- children: ""
208
- });
209
202
  }
210
203
  for (const script of settings.scripts) {
211
204
  if (script.stage === "head-inline") {
@@ -220,7 +213,11 @@ async function getScriptsAndStyles({ pipeline, filePath }) {
220
213
  });
221
214
  }
222
215
  }
223
- const { urls: styleUrls, stylesMap } = await getStylesForURL(filePath, moduleLoader, mode);
216
+ const { urls: styleUrls, styles: importedStyles } = await getStylesForURL(
217
+ filePath,
218
+ moduleLoader,
219
+ mode
220
+ );
224
221
  let links = /* @__PURE__ */ new Set();
225
222
  [...styleUrls].forEach((href) => {
226
223
  links.add({
@@ -232,7 +229,7 @@ async function getScriptsAndStyles({ pipeline, filePath }) {
232
229
  });
233
230
  });
234
231
  let styles = /* @__PURE__ */ new Set();
235
- [...stylesMap].forEach(([url, content]) => {
232
+ importedStyles.forEach(({ id, url, content }) => {
236
233
  scripts.add({
237
234
  props: {
238
235
  type: "module",
@@ -242,8 +239,7 @@ async function getScriptsAndStyles({ pipeline, filePath }) {
242
239
  });
243
240
  styles.add({
244
241
  props: {
245
- // Track the ID so we can match it to Vite's injected style later
246
- "data-astro-dev-id": viteID(new URL(`.${url}`, settings.config.root))
242
+ "data-vite-dev-id": id
247
243
  },
248
244
  children: content
249
245
  });
@@ -0,0 +1,6 @@
1
+ export type MarkdownImagePath = {
2
+ raw: string;
3
+ resolved: string;
4
+ safeName: string;
5
+ };
6
+ export declare function getMarkdownCodeForImages(imagePaths: MarkdownImagePath[], html: string): string;
@@ -0,0 +1,31 @@
1
+ function getMarkdownCodeForImages(imagePaths, html) {
2
+ return `
3
+ import { getImage } from "astro:assets";
4
+ ${imagePaths.map((entry) => `import Astro__${entry.safeName} from ${JSON.stringify(entry.raw)};`).join("\n")}
5
+
6
+ const images = async function() {
7
+ return {
8
+ ${imagePaths.map((entry) => `"${entry.raw}": await getImage({src: Astro__${entry.safeName}})`).join(",\n")}
9
+ }
10
+ }
11
+
12
+ async function updateImageReferences(html) {
13
+ return images().then((images) => {
14
+ return html.replaceAll(/__ASTRO_IMAGE_="([^"]+)"/gm, (full, imagePath) =>
15
+ spreadAttributes({
16
+ src: images[imagePath].src,
17
+ ...images[imagePath].attributes,
18
+ })
19
+ );
20
+ });
21
+ }
22
+
23
+ // NOTE: This causes a top-level await to appear in the user's code, which can break very easily due to a Rollup
24
+ // bug and certain adapters not supporting it correctly. See: https://github.com/rollup/rollup/issues/4708
25
+ // Tread carefully!
26
+ const html = await updateImageReferences(${JSON.stringify(html)});
27
+ `;
28
+ }
29
+ export {
30
+ getMarkdownCodeForImages
31
+ };
@@ -11,6 +11,7 @@ import { AstroError, AstroErrorData, MarkdownError } from "../core/errors/index.
11
11
  import { isMarkdownFile } from "../core/util.js";
12
12
  import { shorthash } from "../runtime/server/shorthash.js";
13
13
  import { escapeViteEnvReferences, getFileInfo } from "../vite-plugin-utils/index.js";
14
+ import { getMarkdownCodeForImages } from "./images.js";
14
15
  function safeMatter(source, id) {
15
16
  try {
16
17
  return matter(source);
@@ -89,29 +90,10 @@ function markdown({ settings, logger }) {
89
90
  astroServerRuntimeModulePath
90
91
  )};
91
92
  import { AstroError, AstroErrorData } from ${JSON.stringify(astroErrorModulePath)};
92
-
93
93
  ${layout ? `import Layout from ${JSON.stringify(layout)};` : ""}
94
- import { getImage } from "astro:assets";
95
- ${imagePaths.map((entry) => `import Astro__${entry.safeName} from ${JSON.stringify(entry.raw)};`).join("\n")}
96
-
97
- const images = async function() {
98
- return {
99
- ${imagePaths.map((entry) => `"${entry.raw}": await getImage({src: Astro__${entry.safeName}})`).join(",\n")}
100
- }
101
- }
102
-
103
- async function updateImageReferences(html) {
104
- return images().then((images) => {
105
- return html.replaceAll(/__ASTRO_IMAGE_="([^"]+)"/gm, (full, imagePath) =>
106
- spreadAttributes({
107
- src: images[imagePath].src,
108
- ...images[imagePath].attributes,
109
- })
110
- );
111
- });
112
- }
113
94
 
114
- const html = await updateImageReferences(${JSON.stringify(html)});
95
+ ${// Only include the code relevant to `astro:assets` if there's images in the file
96
+ imagePaths.length > 0 ? getMarkdownCodeForImages(imagePaths, html) : `const html = ${JSON.stringify(html)};`}
115
97
 
116
98
  export const frontmatter = ${JSON.stringify(frontmatter)};
117
99
  export const file = ${JSON.stringify(fileId)};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
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",
@@ -56,7 +56,7 @@
56
56
  "./components/*": "./components/*",
57
57
  "./assets": "./dist/assets/index.js",
58
58
  "./assets/utils": "./dist/assets/utils/index.js",
59
- "./assets/image-endpoint": "./dist/assets/image-endpoint.js",
59
+ "./assets/endpoint/*": "./dist/assets/endpoint/*.js",
60
60
  "./assets/services/sharp": "./dist/assets/services/sharp.js",
61
61
  "./assets/services/squoosh": "./dist/assets/services/squoosh.js",
62
62
  "./assets/services/noop": "./dist/assets/services/noop.js",