astro 3.0.8 → 3.0.10

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/client.d.ts CHANGED
@@ -52,6 +52,7 @@ declare module 'astro:assets' {
52
52
  | import('./dist/assets/types.js').ImageTransform
53
53
  | import('./dist/assets/types.js').UnresolvedImageTransform
54
54
  ) => Promise<import('./dist/assets/types.js').GetImageResult>;
55
+ imageConfig: import('./dist/@types/astro').AstroConfig['image'];
55
56
  getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
56
57
  Image: typeof import('./components/Image.astro').default;
57
58
  };
@@ -69,7 +70,7 @@ declare module 'astro:assets' {
69
70
  export type RemoteImageProps = Simplify<
70
71
  import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
71
72
  >;
72
- export const { getImage, getConfiguredImageService, Image }: AstroAssets;
73
+ export const { getImage, getConfiguredImageService, imageConfig, Image }: AstroAssets;
73
74
  }
74
75
 
75
76
  type InputFormat = import('./dist/assets/types.js').ImageInputFormat;
@@ -30,9 +30,11 @@ const { fallback = 'animate' } = Astro.props as Props;
30
30
  // The History API does not tell you if navigation is forward or back, so
31
31
  // you can figure it using an index. On pushState the index is incremented so you
32
32
  // can use that to determine popstate if going forward or back.
33
- let currentHistoryIndex = history.state?.index || 0;
34
- if (!history.state && transitionEnabledOnThisPage()) {
35
- persistState({ index: currentHistoryIndex, scrollY: 0 });
33
+ let currentHistoryIndex = 0;
34
+ if (history.state) {
35
+ // we reloaded a page with history state (e.g. back button or browser reload)
36
+ currentHistoryIndex = history.state.index;
37
+ scrollTo({ left: 0, top: history.state.scrollY });
36
38
  }
37
39
 
38
40
  const throttle = (cb: (...args: any[]) => any, delay: number) => {
@@ -100,14 +102,10 @@ const { fallback = 'animate' } = Astro.props as Props;
100
102
 
101
103
  function isInfinite(animation: Animation) {
102
104
  const effect = animation.effect;
103
- if(
104
- !effect ||
105
- !(effect instanceof KeyframeEffect) ||
106
- !effect.target
107
- ) return false;
108
- const style = window.getComputedStyle(effect.target, effect.pseudoElement);
109
- return style.animationIterationCount === "infinite";
110
- }
105
+ if (!effect || !(effect instanceof KeyframeEffect) || !effect.target) return false;
106
+ const style = window.getComputedStyle(effect.target, effect.pseudoElement);
107
+ return style.animationIterationCount === 'infinite';
108
+ }
111
109
 
112
110
  const parser = new DOMParser();
113
111
 
@@ -234,8 +232,10 @@ const { fallback = 'animate' } = Astro.props as Props;
234
232
  // Trigger the animations
235
233
  const currentAnimations = document.getAnimations();
236
234
  document.documentElement.dataset.astroTransitionFallback = 'old';
237
- const newAnimations = document.getAnimations().filter(a => !currentAnimations.includes(a) && !isInfinite(a));
238
- const finished = Promise.all(newAnimations.map(a => a.finished));
235
+ const newAnimations = document
236
+ .getAnimations()
237
+ .filter((a) => !currentAnimations.includes(a) && !isInfinite(a));
238
+ const finished = Promise.all(newAnimations.map((a) => a.finished));
239
239
  const fallbackSwap = () => {
240
240
  swap();
241
241
  document.documentElement.dataset.astroTransitionFallback = 'new';
@@ -352,6 +352,7 @@ const { fallback = 'animate' } = Astro.props as Props;
352
352
  // The current page doesn't haven't View Transitions,
353
353
  // respect that with a full page reload
354
354
  // -- but only for transition managed by us (ev.state is set)
355
+ history.scrollRestoration && (history.scrollRestoration = 'manual');
355
356
  location.reload();
356
357
  return;
357
358
  }
@@ -362,7 +363,7 @@ const { fallback = 'animate' } = Astro.props as Props;
362
363
  // The browser will handle navigation fine without our help
363
364
  if (ev.state === null) {
364
365
  if (history.scrollRestoration) {
365
- history.scrollRestoration = "auto";
366
+ history.scrollRestoration = 'auto';
366
367
  }
367
368
  return;
368
369
  }
@@ -370,7 +371,7 @@ const { fallback = 'animate' } = Astro.props as Props;
370
371
  // With the default "auto", the browser will jump to the old scroll position
371
372
  // before the ViewTransition is complete.
372
373
  if (history.scrollRestoration) {
373
- history.scrollRestoration = "manual";
374
+ history.scrollRestoration = 'manual';
374
375
  }
375
376
 
376
377
  const state: State | undefined = history.state;
@@ -401,13 +402,13 @@ const { fallback = 'animate' } = Astro.props as Props;
401
402
  addEventListener('load', onPageLoad);
402
403
  // There's not a good way to record scroll position before a back button.
403
404
  // So the way we do it is by listening to scrollend if supported, and if not continuously record the scroll position.
404
- const updateState = () => {
405
+ const updateState = () => {
405
406
  // only update history entries that are managed by us
406
407
  // leave other entries alone and do not accidently add state.
407
408
  if (history.state) {
408
409
  persistState({ ...history.state, scrollY });
409
410
  }
410
- }
411
+ };
411
412
  if ('onscrollend' in window) addEventListener('scrollend', updateState);
412
413
  else addEventListener('scroll', throttle(updateState, 300));
413
414
  }
@@ -566,7 +566,7 @@ export interface AstroUserConfig {
566
566
  * import netlify from '@astrojs/netlify/functions';
567
567
  * {
568
568
  * // Example: Build for Netlify serverless deployment
569
- * adapter: netlify(),
569
+ * adapter: netlify(),
570
570
  * }
571
571
  * ```
572
572
  */
@@ -581,9 +581,9 @@ export interface AstroUserConfig {
581
581
  *
582
582
  * Specifies the output target for builds.
583
583
  *
584
- * - 'static' - Building a static site to be deploy to any static host.
585
- * - 'server' - Building an app to be deployed to a host supporting SSR (server-side rendering).
586
- * - 'hybrid' - Building a static site with a few server-side rendered pages.
584
+ * - `'static'` - Building a static site to be deploy to any static host.
585
+ * - `'server'` - Building an app to be deployed to a host supporting SSR (server-side rendering).
586
+ * - `'hybrid'` - Building a static site with a few server-side rendered pages.
587
587
  *
588
588
  * ```js
589
589
  * import { defineConfig } from 'astro/config';
@@ -607,8 +607,8 @@ export interface AstroUserConfig {
607
607
  * @default `'directory'`
608
608
  * @description
609
609
  * Control the output file format of each page.
610
- * - If 'file', Astro will generate an HTML file (ex: "/foo.html") for each page.
611
- * - If 'directory', Astro will generate a directory with a nested `index.html` file (ex: "/foo/index.html") for each page.
610
+ * - If `'file'`, Astro will generate an HTML file (ex: "/foo.html") for each page.
611
+ * - If `'directory'`, Astro will generate a directory with a nested `index.html` file (ex: "/foo/index.html") for each page.
612
612
  *
613
613
  * ```js
614
614
  * {
@@ -885,7 +885,7 @@ export interface AstroUserConfig {
885
885
  /**
886
886
  * @docs
887
887
  * @kind heading
888
- * @name Image options
888
+ * @name Image Options
889
889
  */
890
890
  image?: {
891
891
  /**
@@ -895,7 +895,7 @@ export interface AstroUserConfig {
895
895
  * @default `{entrypoint: 'astro/assets/services/sharp', config?: {}}`
896
896
  * @version 2.1.0
897
897
  * @description
898
- * Set which image service is used for Astro’s experimental assets support.
898
+ * Set which image service is used for Astro’s assets support.
899
899
  *
900
900
  * The value should be an object with an entrypoint for the image service to use and optionally, a config object to pass to the service.
901
901
  *
@@ -918,7 +918,7 @@ export interface AstroUserConfig {
918
918
  * @default `{domains: []}`
919
919
  * @version 2.10.10
920
920
  * @description
921
- * Defines a list of permitted image source domains for local image optimization. No other remote images will be optimized by Astro.
921
+ * Defines a list of permitted image source domains for remote image optimization. No other remote images will be optimized by Astro.
922
922
  *
923
923
  * This option requires an array of individual domain names as strings. Wildcards are not permitted. Instead, use [`image.remotePatterns`](#imageremotepatterns) to define a list of allowed source URL patterns.
924
924
  *
@@ -940,7 +940,7 @@ export interface AstroUserConfig {
940
940
  * @default `{remotePatterns: []}`
941
941
  * @version 2.10.10
942
942
  * @description
943
- * Defines a list of permitted image source URL patterns for local image optimization.
943
+ * Defines a list of permitted image source URL patterns for remote image optimization.
944
944
  *
945
945
  * `remotePatterns` can be configured with four properties:
946
946
  * 1. protocol
@@ -1593,11 +1593,11 @@ export type AstroFeatureMap = {
1593
1593
  export interface AstroAssetsFeature {
1594
1594
  supportKind?: SupportsKind;
1595
1595
  /**
1596
- * Whether if this adapter deploys files in an enviroment that is compatible with the library `sharp`
1596
+ * Whether if this adapter deploys files in an environment that is compatible with the library `sharp`
1597
1597
  */
1598
1598
  isSharpCompatible?: boolean;
1599
1599
  /**
1600
- * Whether if this adapter deploys files in an enviroment that is compatible with the library `squoosh`
1600
+ * Whether if this adapter deploys files in an environment that is compatible with the library `squoosh`
1601
1601
  */
1602
1602
  isSquooshCompatible?: boolean;
1603
1603
  }
@@ -40,7 +40,7 @@ async function generateImage(pipeline, options, filepath) {
40
40
  };
41
41
  } else {
42
42
  const JSONData = JSON.parse(readFileSync(cachedFileURL, "utf-8"));
43
- if (JSONData.expires < Date.now()) {
43
+ if (JSONData.expires > Date.now()) {
44
44
  await fs.promises.writeFile(finalFileURL, Buffer.from(JSONData.data, "base64"));
45
45
  return {
46
46
  cached: true
@@ -6,12 +6,11 @@ import {
6
6
  prependForwardSlash,
7
7
  removeQueryString
8
8
  } from "../core/path.js";
9
- import { VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from "./consts.js";
9
+ import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from "./consts.js";
10
10
  import { emitESMImage } from "./utils/emitAsset.js";
11
11
  import { hashTransform, propsToFilename } from "./utils/transformToPath.js";
12
12
  const resolvedVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
13
- const rawRE = /(?:\?|&)raw(?:&|$)/;
14
- const urlRE = /(\?|&)url(?:&|$)/;
13
+ const assetRegex = new RegExp(`.(${VALID_INPUT_FORMATS.join("|")})$`, "i");
15
14
  function assets({
16
15
  settings,
17
16
  mode
@@ -98,11 +97,10 @@ function assets({
98
97
  resolvedConfig = viteConfig;
99
98
  },
100
99
  async load(id) {
101
- if (rawRE.test(id) || urlRE.test(id)) {
100
+ if (id !== removeQueryString(id)) {
102
101
  return;
103
102
  }
104
- const cleanedUrl = removeQueryString(id);
105
- if (/\.(jpeg|jpg|png|tiff|webp|gif|svg)$/.test(cleanedUrl)) {
103
+ if (assetRegex.test(id)) {
106
104
  const meta = await emitESMImage(id, this.meta.watchMode, this.emitFile);
107
105
  return `export default ${JSON.stringify(meta)}`;
108
106
  }
@@ -511,6 +511,8 @@ async function getInstallIntegrationsCommand({
511
511
  return { pm: "yarn", command: "add", flags: [], dependencies };
512
512
  case "pnpm":
513
513
  return { pm: "pnpm", command: "add", flags: [], dependencies };
514
+ case "bun":
515
+ return { pm: "bun", command: "add", flags: [], dependencies };
514
516
  default:
515
517
  return null;
516
518
  }
@@ -50,6 +50,8 @@ function getInstallCommand(packages, packageManager) {
50
50
  return { pm: "yarn", command: "add", flags: [], dependencies: packages };
51
51
  case "pnpm":
52
52
  return { pm: "pnpm", command: "add", flags: [], dependencies: packages };
53
+ case "bun":
54
+ return { pm: "bun", command: "add", flags: [], dependencies: packages };
53
55
  default:
54
56
  return null;
55
57
  }
@@ -1,8 +1,10 @@
1
+ import whichPm from "which-pm";
1
2
  import * as msg from "../../core/messages.js";
2
3
  import { telemetry } from "../../events/index.js";
3
4
  async function notify() {
5
+ const packageManager = (await whichPm(process.cwd())).name ?? "npm";
4
6
  await telemetry.notify(() => {
5
- console.log(msg.telemetryNotice() + "\n");
7
+ console.log(msg.telemetryNotice(packageManager) + "\n");
6
8
  return true;
7
9
  });
8
10
  }
@@ -94,8 +94,6 @@ class App {
94
94
  }
95
95
  return pathname;
96
96
  }
97
- // Disable no-unused-vars to avoid breaking signature change
98
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
97
  match(request, _opts = {}) {
100
98
  const url = new URL(request.url);
101
99
  if (this.#manifest.assets.has(url.pathname))
@@ -148,13 +148,11 @@ function rollupPluginAstroBuildCSS(options) {
148
148
  async generateBundle(_outputOptions, bundle) {
149
149
  const inlineConfig = settings.config.build.inlineStylesheets;
150
150
  const { assetsInlineLimit = 4096 } = settings.config.vite?.build ?? {};
151
- Object.entries(bundle).forEach(([id, stylesheet]) => {
151
+ Object.entries(bundle).forEach(([_, stylesheet]) => {
152
152
  if (stylesheet.type !== "asset" || stylesheet.name?.endsWith(".css") !== true || typeof stylesheet.source !== "string")
153
153
  return;
154
154
  const assetSize = new TextEncoder().encode(stylesheet.source).byteLength;
155
155
  const toBeInlined = inlineConfig === "always" ? true : inlineConfig === "never" ? false : assetSize <= assetsInlineLimit;
156
- if (toBeInlined)
157
- delete bundle[id];
158
156
  const sheet = toBeInlined ? { type: "inline", content: stylesheet.source } : { type: "external", src: stylesheet.fileName };
159
157
  const pages = Array.from(eachPageData(internals));
160
158
  pages.forEach((pageData) => {
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "3.0.8";
1
+ const ASTRO_VERSION = "3.0.10";
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.0.8";
23
+ const currentVersion = "3.0.10";
24
24
  if (currentVersion.includes("-")) {
25
25
  logger.warn(null, msg.prerelease({ currentVersion }));
26
26
  }
@@ -247,8 +247,8 @@ const InvalidDynamicRoute = {
247
247
  const MissingSharp = {
248
248
  name: "MissingSharp",
249
249
  title: "Could not find Sharp.",
250
- message: "Could not find Sharp. Please install Sharp (`sharp`) manually into your project.",
251
- hint: "See Sharp's installation instructions for more information: https://sharp.pixelplumbing.com/install. If you are not relying on `astro:assets` to optimize, transform, or process any images, you can configure a passthrough image service instead of installing Sharp. See https://docs.astro.build/en/reference/errors/missing-sharp for more information."
250
+ message: "Could not find Sharp. Please install Sharp (`sharp`) manually into your project or migrate to another image service.",
251
+ hint: "See Sharp's installation instructions for more information: https://sharp.pixelplumbing.com/install. If you are not relying on `astro:assets` to optimize, transform, or process any images, you can configure a passthrough image service instead of installing Sharp. See https://docs.astro.build/en/reference/errors/missing-sharp for more information.\n\nSee https://docs.astro.build/en/guides/images/#default-image-service for more information on how to migrate to another image service."
252
252
  };
253
253
  const UnknownViteError = {
254
254
  name: "UnknownViteError",
@@ -22,7 +22,7 @@ export declare function serverStart({ startupTime, resolvedUrls, host, base, isR
22
22
  base: string;
23
23
  isRestart?: boolean;
24
24
  }): string;
25
- export declare function telemetryNotice(): string;
25
+ export declare function telemetryNotice(packageManager?: string): string;
26
26
  export declare function telemetryEnabled(): string;
27
27
  export declare function telemetryDisabled(): string;
28
28
  export declare function telemetryReset(): string;
@@ -50,7 +50,7 @@ function serverStart({
50
50
  base,
51
51
  isRestart = false
52
52
  }) {
53
- const version = "3.0.8";
53
+ const version = "3.0.10";
54
54
  const localPrefix = `${dim("\u2503")} Local `;
55
55
  const networkPrefix = `${dim("\u2503")} Network `;
56
56
  const emptyPrefix = " ".repeat(11);
@@ -79,10 +79,10 @@ function serverStart({
79
79
  ];
80
80
  return messages.filter((msg) => typeof msg === "string").map((msg) => ` ${msg}`).join("\n");
81
81
  }
82
- function telemetryNotice() {
82
+ function telemetryNotice(packageManager = "npm") {
83
83
  const headline = `${cyan("\u25C6")} Astro collects completely anonymous usage data.`;
84
84
  const why = dim(" This optional program helps shape our roadmap.");
85
- const disable = dim(" Run `npm run astro telemetry disable` to opt-out.");
85
+ const disable = dim(` Run \`${packageManager} run astro telemetry disable\` to opt-out.`);
86
86
  const details = ` Details: ${underline("https://astro.build/telemetry")}`;
87
87
  return [headline, why, disable, details].map((v) => " " + v).join("\n");
88
88
  }
@@ -235,7 +235,7 @@ function printHelp({
235
235
  message.push(
236
236
  linebreak(),
237
237
  ` ${bgGreen(black(` ${commandName} `))} ${green(
238
- `v${"3.0.8"}`
238
+ `v${"3.0.10"}`
239
239
  )} ${headline}`
240
240
  );
241
241
  }
@@ -16,6 +16,8 @@ async function renderChild(destination, child) {
16
16
  });
17
17
  });
18
18
  for (const childRender of childRenders) {
19
+ if (!childRender)
20
+ continue;
19
21
  await childRender.renderToFinalDestination(destination);
20
22
  }
21
23
  } else if (typeof child === "function") {
@@ -82,7 +82,7 @@ function markdown({ settings, logger }) {
82
82
  );
83
83
  }
84
84
  const code = escapeViteEnvReferences(`
85
- import { unescapeHTML, spreadAttributes, createComponent, render, renderComponent } from ${JSON.stringify(
85
+ import { unescapeHTML, spreadAttributes, createComponent, render, renderComponent, maybeRenderHead } from ${JSON.stringify(
86
86
  astroServerRuntimeModulePath
87
87
  )};
88
88
  import { AstroError, AstroErrorData } from ${JSON.stringify(astroErrorModulePath)};
@@ -149,9 +149,8 @@ function markdown({ settings, logger }) {
149
149
  'server:root': true,
150
150
  }, {
151
151
  'default': () => render\`\${unescapeHTML(html)}\`
152
- })}\`;` : `render\`\${unescapeHTML(html)}\`;`}
152
+ })}\`;` : `render\`\${maybeRenderHead(result)}\${unescapeHTML(html)}\`;`}
153
153
  });
154
- Content[Symbol.for('astro.needsHeadRendering')] = ${layout ? "false" : "true"};
155
154
  export default Content;
156
155
  `);
157
156
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
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",
@@ -140,13 +140,12 @@
140
140
  "ora": "^7.0.1",
141
141
  "p-limit": "^4.0.0",
142
142
  "path-to-regexp": "^6.2.1",
143
- "preferred-pm": "^3.0.3",
143
+ "preferred-pm": "^3.1.2",
144
144
  "prompts": "^2.4.2",
145
145
  "rehype": "^12.0.1",
146
146
  "resolve": "^1.22.4",
147
147
  "semver": "^7.5.4",
148
148
  "server-destroy": "^1.0.1",
149
- "sharp": "^0.32.5",
150
149
  "shiki": "^0.14.3",
151
150
  "string-width": "^6.1.0",
152
151
  "strip-ansi": "^7.1.0",
@@ -156,13 +155,16 @@
156
155
  "vfile": "^5.3.7",
157
156
  "vite": "^4.4.9",
158
157
  "vitefu": "^0.2.4",
159
- "which-pm": "^2.0.0",
158
+ "which-pm": "^2.1.1",
160
159
  "yargs-parser": "^21.1.1",
161
160
  "zod": "3.21.1",
162
161
  "@astrojs/internal-helpers": "0.2.0",
163
162
  "@astrojs/markdown-remark": "3.0.0",
164
163
  "@astrojs/telemetry": "3.0.1"
165
164
  },
165
+ "optionalDependencies": {
166
+ "sharp": "^0.32.5"
167
+ },
166
168
  "devDependencies": {
167
169
  "@astrojs/check": "^0.1.0",
168
170
  "@playwright/test": "^1.37.1",