astro 5.8.0 → 5.8.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.
@@ -71,7 +71,7 @@ function assets({ fs, settings, sync, logger }) {
71
71
  globalThis.astroAsset = {
72
72
  referencedImages: /* @__PURE__ */ new Set()
73
73
  };
74
- const imageComponentPrefix = settings.config.experimental.responsiveImages ? "Responsive" : "";
74
+ const imageComponentPrefix = settings.config.experimental.responsiveImages && settings.config.image.experimentalDefaultStyles ? "Responsive" : "";
75
75
  return [
76
76
  // Expose the components and different utilities from `astro:assets`
77
77
  {
@@ -153,7 +153,7 @@ ${contentConfig.error.message}`);
153
153
  logger.info("Content config changed");
154
154
  shouldClear = true;
155
155
  }
156
- if (previousAstroVersion && previousAstroVersion !== "5.8.0") {
156
+ if (previousAstroVersion && previousAstroVersion !== "5.8.2") {
157
157
  logger.info("Astro version changed");
158
158
  shouldClear = true;
159
159
  }
@@ -161,8 +161,8 @@ ${contentConfig.error.message}`);
161
161
  logger.info("Clearing content store");
162
162
  this.#store.clearAll();
163
163
  }
164
- if ("5.8.0") {
165
- await this.#store.metaStore().set("astro-version", "5.8.0");
164
+ if ("5.8.2") {
165
+ await this.#store.metaStore().set("astro-version", "5.8.2");
166
166
  }
167
167
  if (currentConfigDigest) {
168
168
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -41,6 +41,7 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
41
41
  entrypoint: "astro/assets/services/sharp";
42
42
  config: {};
43
43
  };
44
+ experimentalDefaultStyles: true;
44
45
  };
45
46
  devToolbar: {
46
47
  enabled: true;
@@ -244,7 +245,9 @@ export declare const AstroConfigSchema: z.ZodObject<{
244
245
  experimentalObjectFit: z.ZodOptional<z.ZodString>;
245
246
  experimentalObjectPosition: z.ZodOptional<z.ZodString>;
246
247
  experimentalBreakpoints: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
248
+ experimentalDefaultStyles: z.ZodDefault<z.ZodBoolean>;
247
249
  }, "strip", z.ZodTypeAny, {
250
+ experimentalDefaultStyles: boolean;
248
251
  endpoint: {
249
252
  route: string;
250
253
  entrypoint?: string | undefined;
@@ -265,6 +268,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
265
268
  experimentalObjectPosition?: string | undefined;
266
269
  experimentalBreakpoints?: number[] | undefined;
267
270
  }, {
271
+ experimentalDefaultStyles?: boolean | undefined;
268
272
  endpoint?: {
269
273
  entrypoint?: string | undefined;
270
274
  route?: string | undefined;
@@ -1091,6 +1095,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
1091
1095
  };
1092
1096
  }[];
1093
1097
  image: {
1098
+ experimentalDefaultStyles: boolean;
1094
1099
  endpoint: {
1095
1100
  route: string;
1096
1101
  entrypoint?: string | undefined;
@@ -1323,6 +1328,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
1323
1328
  defaultStrategy?: "load" | "tap" | "hover" | "viewport" | undefined;
1324
1329
  } | undefined;
1325
1330
  image?: {
1331
+ experimentalDefaultStyles?: boolean | undefined;
1326
1332
  endpoint?: {
1327
1333
  entrypoint?: string | undefined;
1328
1334
  route?: string | undefined;
@@ -23,7 +23,8 @@ const ASTRO_CONFIG_DEFAULTS = {
23
23
  },
24
24
  image: {
25
25
  endpoint: { entrypoint: void 0, route: "/_image" },
26
- service: { entrypoint: "astro/assets/services/sharp", config: {} }
26
+ service: { entrypoint: "astro/assets/services/sharp", config: {} },
27
+ experimentalDefaultStyles: true
27
28
  },
28
29
  devToolbar: {
29
30
  enabled: true
@@ -149,7 +150,8 @@ const AstroConfigSchema = z.object({
149
150
  experimentalLayout: z.enum(["constrained", "fixed", "full-width", "none"]).optional(),
150
151
  experimentalObjectFit: z.string().optional(),
151
152
  experimentalObjectPosition: z.string().optional(),
152
- experimentalBreakpoints: z.array(z.number()).optional()
153
+ experimentalBreakpoints: z.array(z.number()).optional(),
154
+ experimentalDefaultStyles: z.boolean().default(ASTRO_CONFIG_DEFAULTS.image.experimentalDefaultStyles)
153
155
  }).default(ASTRO_CONFIG_DEFAULTS.image),
154
156
  devToolbar: z.object({
155
157
  enabled: z.boolean().default(ASTRO_CONFIG_DEFAULTS.devToolbar.enabled)
@@ -169,7 +169,9 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
169
169
  experimentalObjectFit: z.ZodOptional<z.ZodString>;
170
170
  experimentalObjectPosition: z.ZodOptional<z.ZodString>;
171
171
  experimentalBreakpoints: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
172
+ experimentalDefaultStyles: z.ZodDefault<z.ZodBoolean>;
172
173
  }, "strip", z.ZodTypeAny, {
174
+ experimentalDefaultStyles: boolean;
173
175
  endpoint: {
174
176
  route: string;
175
177
  entrypoint?: string | undefined;
@@ -190,6 +192,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
190
192
  experimentalObjectPosition?: string | undefined;
191
193
  experimentalBreakpoints?: number[] | undefined;
192
194
  }, {
195
+ experimentalDefaultStyles?: boolean | undefined;
193
196
  endpoint?: {
194
197
  entrypoint?: string | undefined;
195
198
  route?: string | undefined;
@@ -1094,6 +1097,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1094
1097
  };
1095
1098
  }[];
1096
1099
  image: {
1100
+ experimentalDefaultStyles: boolean;
1097
1101
  endpoint: {
1098
1102
  route: string;
1099
1103
  entrypoint?: string | undefined;
@@ -1326,6 +1330,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1326
1330
  defaultStrategy?: "load" | "tap" | "hover" | "viewport" | undefined;
1327
1331
  } | undefined;
1328
1332
  image?: {
1333
+ experimentalDefaultStyles?: boolean | undefined;
1329
1334
  endpoint?: {
1330
1335
  entrypoint?: string | undefined;
1331
1336
  route?: string | undefined;
@@ -1550,6 +1555,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1550
1555
  };
1551
1556
  }[];
1552
1557
  image: {
1558
+ experimentalDefaultStyles: boolean;
1553
1559
  endpoint: {
1554
1560
  route: string;
1555
1561
  entrypoint?: string | undefined;
@@ -1782,6 +1788,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
1782
1788
  defaultStrategy?: "load" | "tap" | "hover" | "viewport" | undefined;
1783
1789
  } | undefined;
1784
1790
  image?: {
1791
+ experimentalDefaultStyles?: boolean | undefined;
1785
1792
  endpoint?: {
1786
1793
  entrypoint?: string | undefined;
1787
1794
  route?: string | undefined;
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.8.0";
1
+ const ASTRO_VERSION = "5.8.2";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
4
4
  const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
22
22
  await telemetry.record([]);
23
23
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
24
24
  const logger = restart.container.logger;
25
- const currentVersion = "5.8.0";
25
+ const currentVersion = "5.8.2";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -37,7 +37,7 @@ function serverStart({
37
37
  host,
38
38
  base
39
39
  }) {
40
- const version = "5.8.0";
40
+ const version = "5.8.2";
41
41
  const localPrefix = `${dim("\u2503")} Local `;
42
42
  const networkPrefix = `${dim("\u2503")} Network `;
43
43
  const emptyPrefix = " ".repeat(11);
@@ -274,7 +274,7 @@ function printHelp({
274
274
  message.push(
275
275
  linebreak(),
276
276
  ` ${bgGreen(black(` ${commandName} `))} ${green(
277
- `v${"5.8.0"}`
277
+ `v${"5.8.2"}`
278
278
  )} ${headline}`
279
279
  );
280
280
  }
@@ -25,11 +25,11 @@ function sequence(...handlers) {
25
25
  if (payload instanceof Request) {
26
26
  newRequest = payload;
27
27
  } else if (payload instanceof URL) {
28
- newRequest = new Request(payload, handleContext.request);
28
+ newRequest = new Request(payload, handleContext.request.clone());
29
29
  } else {
30
30
  newRequest = new Request(
31
31
  new URL(payload, handleContext.url.origin),
32
- handleContext.request
32
+ handleContext.request.clone()
33
33
  );
34
34
  }
35
35
  const oldPathname = handleContext.url.pathname;
@@ -26,42 +26,37 @@ function vitePluginServerIslands({ settings, logger }) {
26
26
  }
27
27
  },
28
28
  transform(_code, id) {
29
- if (id.endsWith(".astro")) {
30
- const info = this.getModuleInfo(id);
31
- if (info?.meta) {
32
- const astro = info.meta.astro;
33
- if (astro?.serverComponents.length) {
34
- for (const comp of astro.serverComponents) {
35
- if (!settings.serverIslandNameMap.has(comp.resolvedPath)) {
36
- if (!settings.adapter) {
37
- logger.error(
38
- "islands",
39
- "You tried to render a server island without an adapter added to your project. An adapter is required to use the `server:defer` attribute on any component. Your project will fail to build unless you add an adapter or remove the attribute."
40
- );
41
- }
42
- let name = comp.localName;
43
- let idx = 1;
44
- while (true) {
45
- if (!settings.serverIslandMap.has(name)) {
46
- break;
47
- }
48
- name += idx++;
49
- }
50
- settings.serverIslandNameMap.set(comp.resolvedPath, name);
51
- settings.serverIslandMap.set(name, () => {
52
- return viteServer?.ssrLoadModule(comp.resolvedPath);
53
- });
54
- if (command === "build") {
55
- let referenceId = this.emitFile({
56
- type: "chunk",
57
- id: comp.specifier,
58
- importer: id,
59
- name: comp.localName
60
- });
61
- referenceIdMap.set(comp.resolvedPath, referenceId);
62
- }
63
- }
29
+ const info = this.getModuleInfo(id);
30
+ if (!info?.meta?.astro) return;
31
+ const astro = info.meta.astro;
32
+ for (const comp of astro.serverComponents) {
33
+ if (!settings.serverIslandNameMap.has(comp.resolvedPath)) {
34
+ if (!settings.adapter) {
35
+ logger.error(
36
+ "islands",
37
+ "You tried to render a server island without an adapter added to your project. An adapter is required to use the `server:defer` attribute on any component. Your project will fail to build unless you add an adapter or remove the attribute."
38
+ );
39
+ }
40
+ let name = comp.localName;
41
+ let idx = 1;
42
+ while (true) {
43
+ if (!settings.serverIslandMap.has(name)) {
44
+ break;
64
45
  }
46
+ name += idx++;
47
+ }
48
+ settings.serverIslandNameMap.set(comp.resolvedPath, name);
49
+ settings.serverIslandMap.set(name, () => {
50
+ return viteServer?.ssrLoadModule(comp.resolvedPath);
51
+ });
52
+ if (command === "build") {
53
+ let referenceId = this.emitFile({
54
+ type: "chunk",
55
+ id: comp.specifier,
56
+ importer: id,
57
+ name: comp.localName
58
+ });
59
+ referenceIdMap.set(comp.resolvedPath, referenceId);
65
60
  }
66
61
  }
67
62
  }
@@ -11,7 +11,8 @@ const rehypeAnalyzeAstroMetadata = () => {
11
11
  visit(tree, (node) => {
12
12
  if (node.type !== "mdxJsxFlowElement" && node.type !== "mdxJsxTextElement") return;
13
13
  const tagName = node.name;
14
- if (!tagName || !isComponent(tagName) || !hasClientDirective(node)) return;
14
+ if (!tagName || !isComponent(tagName) || !(hasClientDirective(node) || hasServerDeferDirective(node)))
15
+ return;
15
16
  const matchedImport = findMatchingImport(tagName, imports);
16
17
  if (!matchedImport) {
17
18
  throw new AstroError({
@@ -38,7 +39,7 @@ const rehypeAnalyzeAstroMetadata = () => {
38
39
  resolvedPath
39
40
  });
40
41
  addClientOnlyMetadata(node, matchedImport, resolvedPath);
41
- } else {
42
+ } else if (hasClientDirective(node)) {
42
43
  metadata.hydratedComponents.push({
43
44
  exportName: "*",
44
45
  localName: "",
@@ -46,6 +47,14 @@ const rehypeAnalyzeAstroMetadata = () => {
46
47
  resolvedPath
47
48
  });
48
49
  addClientMetadata(node, matchedImport, resolvedPath);
50
+ } else if (hasServerDeferDirective(node)) {
51
+ metadata.serverComponents.push({
52
+ exportName: matchedImport.name,
53
+ localName: tagName,
54
+ specifier: matchedImport.path,
55
+ resolvedPath
56
+ });
57
+ addServerDeferMetadata(node, matchedImport, resolvedPath);
49
58
  }
50
59
  });
51
60
  file.data.__astroMetadata = metadata;
@@ -99,6 +108,11 @@ function hasClientDirective(node) {
99
108
  (attr) => attr.type === "mdxJsxAttribute" && attr.name.startsWith("client:")
100
109
  );
101
110
  }
111
+ function hasServerDeferDirective(node) {
112
+ return node.attributes.some(
113
+ (attr) => attr.type === "mdxJsxAttribute" && attr.name === "server:defer"
114
+ );
115
+ }
102
116
  function hasClientOnlyDirective(node) {
103
117
  return node.attributes.some(
104
118
  (attr) => attr.type === "mdxJsxAttribute" && attr.name === "client:only"
@@ -194,6 +208,33 @@ function addClientOnlyMetadata(node, meta, resolvedPath) {
194
208
  }
195
209
  node.name = ClientOnlyPlaceholder;
196
210
  }
211
+ function addServerDeferMetadata(node, meta, resolvedPath) {
212
+ const attributeNames = node.attributes.map((attr) => attr.type === "mdxJsxAttribute" ? attr.name : null).filter(Boolean);
213
+ if (!attributeNames.includes("server:component-directive")) {
214
+ node.attributes.push({
215
+ type: "mdxJsxAttribute",
216
+ name: "server:component-directive",
217
+ value: "server:defer"
218
+ });
219
+ }
220
+ if (!attributeNames.includes("server:component-path")) {
221
+ node.attributes.push({
222
+ type: "mdxJsxAttribute",
223
+ name: "server:component-path",
224
+ value: resolvedPath
225
+ });
226
+ }
227
+ if (!attributeNames.includes("server:component-export")) {
228
+ if (meta.name === "*") {
229
+ meta.name = node.name.split(".").slice(1).join(".");
230
+ }
231
+ node.attributes.push({
232
+ type: "mdxJsxAttribute",
233
+ name: "server:component-export",
234
+ value: meta.name
235
+ });
236
+ }
237
+ }
197
238
  export {
198
239
  getAstroMetadata,
199
240
  rehypeAnalyzeAstroMetadata
@@ -3,10 +3,10 @@ import {
3
3
  HTMLString,
4
4
  escapeHTML,
5
5
  markHTMLString,
6
- renderToString,
7
6
  spreadAttributes,
8
7
  voidElementNames
9
8
  } from "./index.js";
9
+ import { isAstroComponentFactory } from "./render/astro/factory.js";
10
10
  import { renderComponentToString } from "./render/component.js";
11
11
  const ClientOnlyPlaceholder = "astro-client-only";
12
12
  const hasTriedRenderComponentSymbol = Symbol("hasTriedRenderComponent");
@@ -39,7 +39,7 @@ Did you forget to import the component or is it possible there is a typo?`);
39
39
  }
40
40
  case vnode.type === Symbol.for("astro:fragment"):
41
41
  return renderJSX(result, vnode.props.children);
42
- case vnode.type.isAstroComponentFactory: {
42
+ case isAstroComponentFactory(vnode.type): {
43
43
  let props = {};
44
44
  let slots = {};
45
45
  for (const [key, value] of Object.entries(vnode.props ?? {})) {
@@ -49,10 +49,13 @@ Did you forget to import the component or is it possible there is a typo?`);
49
49
  props[key] = value;
50
50
  }
51
51
  }
52
- const str = await renderToString(result, vnode.type, props, slots);
53
- if (str instanceof Response) {
54
- throw str;
55
- }
52
+ const str = await renderComponentToString(
53
+ result,
54
+ vnode.type.name,
55
+ vnode.type,
56
+ props,
57
+ slots
58
+ );
56
59
  const html = markHTMLString(str);
57
60
  return html;
58
61
  }
@@ -55,10 +55,11 @@ class AstroComponentInstance {
55
55
  }
56
56
  }
57
57
  }
58
- function validateComponentProps(props, displayName) {
58
+ function validateComponentProps(props, clientDirectives, displayName) {
59
59
  if (props != null) {
60
+ const directives = [...clientDirectives.keys()].map((directive) => `client:${directive}`);
60
61
  for (const prop of Object.keys(props)) {
61
- if (prop.startsWith("client:")) {
62
+ if (directives.includes(prop)) {
62
63
  console.warn(
63
64
  `You are attempting to render <${displayName} ${prop} />, but ${displayName} is an Astro component. Astro components do not render in the client and should not have a hydration directive. Please use a framework component for client rendering.`
64
65
  );
@@ -67,7 +68,7 @@ function validateComponentProps(props, displayName) {
67
68
  }
68
69
  }
69
70
  function createAstroComponentInstance(result, displayName, factory, props, slots = {}) {
70
- validateComponentProps(props, displayName);
71
+ validateComponentProps(props, result.clientDirectives, displayName);
71
72
  const instance = new AstroComponentInstance(result, props, slots, factory);
72
73
  if (isAPropagatingComponent(result, factory)) {
73
74
  result._metadata.propagators.add(instance);
@@ -72,6 +72,12 @@ Make sure to use the static attribute syntax (\`${key}={value}\`) instead of the
72
72
  if (value === "") {
73
73
  return markHTMLString(` ${key}`);
74
74
  }
75
+ if (key === "popover" && typeof value === "boolean") {
76
+ return markHTMLString(value ? ` popover` : "");
77
+ }
78
+ if (key === "download" && typeof value === "boolean") {
79
+ return markHTMLString(value ? ` download` : "");
80
+ }
75
81
  return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`);
76
82
  }
77
83
  function internalSpreadAttributes(values, shouldEscape = true) {
@@ -1282,6 +1282,16 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
1282
1282
  * the more comprehensive list is used, because only the required sizes are generated. For local services, the list is shorter to reduce the number of images generated.
1283
1283
  */
1284
1284
  experimentalBreakpoints?: number[];
1285
+ /**
1286
+ * @docs
1287
+ * @name image.experimentalDefaultStyles
1288
+ * @type {boolean}
1289
+ * @default `true`
1290
+ * @description
1291
+ * Whether to automatically add global styles to ensure that experimental images resize correctly. This is enabled by default, but can be disabled if you want to manage the styles yourself.
1292
+ * This option is only used when the `experimental.responsiveImages` flag is enabled.
1293
+ */
1294
+ experimentalDefaultStyles?: boolean;
1285
1295
  };
1286
1296
  /**
1287
1297
  * @docs
@@ -19,3 +19,4 @@ export type { GetImageResult, ImageInputFormat, ImageMetadata, ImageOutputFormat
19
19
  export type { AssetsPrefix, SSRManifest } from '../../core/app/types.js';
20
20
  export type { AstroCookieGetOptions, AstroCookieSetOptions, AstroCookies, } from '../../core/cookies/index.js';
21
21
  export type { ContainerRenderer } from '../../container/index.js';
22
+ export { AstroSession } from '../../core/session.js';
@@ -0,0 +1,4 @@
1
+ import { AstroSession } from "../../core/session.js";
2
+ export {
3
+ AstroSession
4
+ };
@@ -5,6 +5,7 @@ import { warnMissingAdapter } from "../core/dev/adapter-validation.js";
5
5
  import { getRoutePrerenderOption } from "../core/routing/manifest/prerender.js";
6
6
  import { isEndpoint, isPage } from "../core/util.js";
7
7
  import { normalizePath, rootRelativePath } from "../core/viteUtils.js";
8
+ import { createDefaultAstroMetadata } from "../vite-plugin-astro/metadata.js";
8
9
  const KNOWN_FILE_EXTENSIONS = [".astro", ".js", ".ts"];
9
10
  function astroScannerPlugin({
10
11
  settings,
@@ -49,7 +50,7 @@ function astroScannerPlugin({
49
50
  meta: {
50
51
  ...meta,
51
52
  astro: {
52
- ...meta.astro ?? { hydratedComponents: [], clientOnlyComponents: [], scripts: [] },
53
+ ...meta.astro ?? createDefaultAstroMetadata(),
53
54
  pageOptions: {
54
55
  prerender: route.prerender
55
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.8.0",
3
+ "version": "5.8.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",