astro 3.0.10 → 3.0.12

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
@@ -57,17 +57,15 @@ declare module 'astro:assets' {
57
57
  Image: typeof import('./components/Image.astro').default;
58
58
  };
59
59
 
60
- type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
61
- type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
62
- type ImgAttributes = WithRequired<
60
+ type ImgAttributes = import('./dist/type-utils.js').WithRequired<
63
61
  Omit<import('./types').HTMLAttributes<'img'>, 'src' | 'width' | 'height'>,
64
62
  'alt'
65
63
  >;
66
64
 
67
- export type LocalImageProps = Simplify<
65
+ export type LocalImageProps = import('./dist/type-utils.js').Simplify<
68
66
  import('./dist/assets/types.js').LocalImageProps<ImgAttributes>
69
67
  >;
70
- export type RemoteImageProps = Simplify<
68
+ export type RemoteImageProps = import('./dist/type-utils.js').Simplify<
71
69
  import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
72
70
  >;
73
71
  export const { getImage, getConfiguredImageService, imageConfig, Image }: AstroAssets;
@@ -19,7 +19,9 @@ const { fallback = 'animate' } = Astro.props as Props;
19
19
  };
20
20
  type Events = 'astro:page-load' | 'astro:after-swap';
21
21
 
22
- const persistState = (state: State) => history.replaceState(state, '');
22
+ // only update history entries that are managed by us
23
+ // leave other entries alone and do not accidently add state.
24
+ const persistState = (state: State) => history.state && history.replaceState(state, '');
23
25
  const supportsViewTransitions = !!document.startViewTransition;
24
26
  const transitionEnabledOnThisPage = () =>
25
27
  !!document.querySelector('[name="astro-view-transitions-enabled"]');
@@ -32,11 +34,13 @@ const { fallback = 'animate' } = Astro.props as Props;
32
34
  // can use that to determine popstate if going forward or back.
33
35
  let currentHistoryIndex = 0;
34
36
  if (history.state) {
35
- // we reloaded a page with history state (e.g. back button or browser reload)
37
+ // we reloaded a page with history state
38
+ // (e.g. history navigation from non-transition page or browser reload)
36
39
  currentHistoryIndex = history.state.index;
37
40
  scrollTo({ left: 0, top: history.state.scrollY });
41
+ } else if (transitionEnabledOnThisPage()) {
42
+ history.replaceState({ index: currentHistoryIndex, scrollY }, '');
38
43
  }
39
-
40
44
  const throttle = (cb: (...args: any[]) => any, delay: number) => {
41
45
  let wait = false;
42
46
  // During the waiting time additional events are lost.
@@ -109,9 +113,7 @@ const { fallback = 'animate' } = Astro.props as Props;
109
113
 
110
114
  const parser = new DOMParser();
111
115
 
112
- async function updateDOM(html: string, state?: State, fallback?: Fallback) {
113
- const doc = parser.parseFromString(html, 'text/html');
114
-
116
+ async function updateDOM(doc: Document, loc: URL, state?: State, fallback?: Fallback) {
115
117
  // Check for a head element that should persist, either because it has the data
116
118
  // attribute or is a link el.
117
119
  const persistedHeadElement = (el: Element): Element | null => {
@@ -189,19 +191,17 @@ const { fallback = 'animate' } = Astro.props as Props;
189
191
  // Chromium based browsers (Chrome, Edge, Opera, ...)
190
192
  scrollTo({ left: 0, top: 0, behavior: 'instant' });
191
193
 
192
- if (state?.scrollY === 0 && location.hash) {
193
- const id = decodeURIComponent(location.hash.slice(1));
194
+ let initialScrollY = 0;
195
+ if (!state && loc.hash) {
196
+ const id = decodeURIComponent(loc.hash.slice(1));
194
197
  const elem = document.getElementById(id);
195
198
  // prefer scrollIntoView() over scrollTo() because it takes scroll-padding into account
196
- if (elem) {
197
- state.scrollY = elem.offsetTop;
198
- persistState(state); // first guess, later updated by scroll handler
199
- elem.scrollIntoView(); // for Firefox, this should better be {behavior: 'instant'}
200
- }
199
+ elem && (initialScrollY = elem.offsetTop) && elem.scrollIntoView();
201
200
  } else if (state && state.scrollY !== 0) {
202
201
  scrollTo(0, state.scrollY); // usings default scrollBehavior
203
202
  }
204
-
203
+ !state &&
204
+ history.pushState({ index: ++currentHistoryIndex, scrollY: initialScrollY }, '', loc.href);
205
205
  triggerEvent('astro:after-swap');
206
206
  };
207
207
 
@@ -247,19 +247,26 @@ const { fallback = 'animate' } = Astro.props as Props;
247
247
  }
248
248
  }
249
249
 
250
- async function navigate(dir: Direction, href: string, state?: State) {
250
+ async function navigate(dir: Direction, loc: URL, state?: State) {
251
251
  let finished: Promise<void>;
252
+ const href = loc.href;
252
253
  const { html, ok } = await getHTML(href);
253
254
  // If there is a problem fetching the new page, just do an MPA navigation to it.
254
255
  if (!ok) {
255
256
  location.href = href;
256
257
  return;
257
258
  }
259
+ const doc = parser.parseFromString(html, 'text/html');
260
+ if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) {
261
+ location.href = href;
262
+ return;
263
+ }
264
+
258
265
  document.documentElement.dataset.astroTransition = dir;
259
266
  if (supportsViewTransitions) {
260
- finished = document.startViewTransition(() => updateDOM(html, state)).finished;
267
+ finished = document.startViewTransition(() => updateDOM(doc, loc, state)).finished;
261
268
  } else {
262
- finished = updateDOM(html, state, getFallback());
269
+ finished = updateDOM(doc, loc, state, getFallback());
263
270
  }
264
271
  try {
265
272
  await finished;
@@ -311,11 +318,11 @@ const { fallback = 'animate' } = Astro.props as Props;
311
318
  ev.shiftKey || // new window
312
319
  ev.defaultPrevented ||
313
320
  !transitionEnabledOnThisPage()
314
- )
321
+ ) {
315
322
  // No page transitions in these cases,
316
323
  // Let the browser standard action handle this
317
324
  return;
318
-
325
+ }
319
326
  // We do not need to handle same page links because there are no page transitions
320
327
  // Same page means same path and same query params (but different hash)
321
328
  if (location.pathname === link.pathname && location.search === link.search) {
@@ -341,10 +348,8 @@ const { fallback = 'animate' } = Astro.props as Props;
341
348
 
342
349
  // these are the cases we will handle: same origin, different page
343
350
  ev.preventDefault();
344
- navigate('forward', link.href, { index: ++currentHistoryIndex, scrollY: 0 });
345
- const newState: State = { index: currentHistoryIndex, scrollY };
346
- persistState({ index: currentHistoryIndex - 1, scrollY });
347
- history.pushState(newState, '', link.href);
351
+ persistState({ index: currentHistoryIndex, scrollY });
352
+ navigate('forward', new URL(link.href));
348
353
  });
349
354
 
350
355
  addEventListener('popstate', (ev) => {
@@ -374,11 +379,11 @@ const { fallback = 'animate' } = Astro.props as Props;
374
379
  history.scrollRestoration = 'manual';
375
380
  }
376
381
 
377
- const state: State | undefined = history.state;
378
- const nextIndex = state?.index ?? currentHistoryIndex + 1;
382
+ const state: State = history.state;
383
+ const nextIndex = state.index;
379
384
  const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back';
380
- navigate(direction, location.href, state);
381
385
  currentHistoryIndex = nextIndex;
386
+ navigate(direction, new URL(location.href), state);
382
387
  });
383
388
 
384
389
  ['mouseenter', 'touchstart', 'focus'].forEach((evName) => {
@@ -403,12 +408,9 @@ const { fallback = 'animate' } = Astro.props as Props;
403
408
  // There's not a good way to record scroll position before a back button.
404
409
  // So the way we do it is by listening to scrollend if supported, and if not continuously record the scroll position.
405
410
  const updateState = () => {
406
- // only update history entries that are managed by us
407
- // leave other entries alone and do not accidently add state.
408
- if (history.state) {
409
- persistState({ ...history.state, scrollY });
410
- }
411
+ persistState({ ...history.state, scrollY });
411
412
  };
413
+
412
414
  if ('onscrollend' in window) addEventListener('scrollend', updateState);
413
415
  else addEventListener('scroll', throttle(updateState, 300));
414
416
  }
@@ -17,6 +17,7 @@ import type { AstroCookies } from '../core/cookies';
17
17
  import type { ResponseWithEncoding } from '../core/endpoint/index.js';
18
18
  import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger/core';
19
19
  import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server';
20
+ import type { OmitIndexSignature, Simplify } from '../type-utils';
20
21
  import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
21
22
  export { type AstroIntegrationLogger };
22
23
  export type { MarkdownHeading, MarkdownMetadata, MarkdownRenderingResult, RehypePlugins, RemarkPlugins, ShikiConfig, } from '@astrojs/markdown-remark';
@@ -1556,12 +1557,6 @@ export interface Page<T = any> {
1556
1557
  next: string | undefined;
1557
1558
  };
1558
1559
  }
1559
- type OmitIndexSignature<ObjectType> = {
1560
- [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType];
1561
- };
1562
- type Simplify<T> = {
1563
- [KeyType in keyof T]: T[KeyType];
1564
- } & {};
1565
1560
  export type PaginateFunction = <PaginateData, AdditionalPaginateProps extends Props, AdditionalPaginateParams extends Params>(data: PaginateData[], args?: PaginateOptions<AdditionalPaginateProps, AdditionalPaginateParams>) => {
1566
1561
  params: Simplify<{
1567
1562
  page: string | undefined;
@@ -1,3 +1,4 @@
1
+ import type { WithRequired } from '../type-utils.js';
1
2
  import type { VALID_INPUT_FORMATS, VALID_OUTPUT_FORMATS } from './consts.js';
2
3
  import type { ImageService } from './services/service.js';
3
4
  export type ImageQualityPreset = 'low' | 'mid' | 'high' | 'max' | (string & {});
@@ -46,9 +47,6 @@ export interface GetImageResult {
46
47
  src: string;
47
48
  attributes: Record<string, any>;
48
49
  }
49
- type WithRequired<T, K extends keyof T> = T & {
50
- [P in K]-?: T[P];
51
- };
52
50
  type ImageSharedProps<T> = T & {
53
51
  /**
54
52
  * Width of the image, the value of this property will be used to assign the `width` property on the final `img` element.
@@ -2,7 +2,7 @@ import whichPm from "which-pm";
2
2
  import * as msg from "../../core/messages.js";
3
3
  import { telemetry } from "../../events/index.js";
4
4
  async function notify() {
5
- const packageManager = (await whichPm(process.cwd())).name ?? "npm";
5
+ const packageManager = (await whichPm(process.cwd()))?.name ?? "npm";
6
6
  await telemetry.notify(() => {
7
7
  console.log(msg.telemetryNotice(packageManager) + "\n");
8
8
  return true;
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "3.0.10";
1
+ const ASTRO_VERSION = "3.0.12";
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.10";
23
+ const currentVersion = "3.0.12";
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.0.10";
53
+ const version = "3.0.12";
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.0.10"}`
238
+ `v${"3.0.12"}`
239
239
  )} ${headline}`
240
240
  );
241
241
  }
@@ -0,0 +1,10 @@
1
+ export type Simplify<T> = {
2
+ [KeyType in keyof T]: T[KeyType];
3
+ } & {};
4
+ export type WithRequired<T, K extends keyof T> = T & {
5
+ [P in K]-?: T[P];
6
+ };
7
+ export type OmitIndexSignature<ObjectType> = {
8
+ [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType];
9
+ };
10
+ export type ValueOf<T> = T[keyof T];
File without changes
@@ -125,7 +125,7 @@ File: ${id}`
125
125
  hydratedComponents: transformResult.hydratedComponents,
126
126
  scripts: transformResult.scripts,
127
127
  containsHead: transformResult.containsHead,
128
- propagation: "none",
128
+ propagation: transformResult.propagation ? "self" : "none",
129
129
  pageOptions: {}
130
130
  };
131
131
  return {
@@ -34,6 +34,14 @@ function configHeadVitePlugin() {
34
34
  if (info && getAstroMetadata(info)?.containsHead) {
35
35
  propagateMetadata.call(this, id, "containsHead", true);
36
36
  }
37
+ if (info && getAstroMetadata(info)?.propagation === "self") {
38
+ const mod = server.moduleGraph.getModuleById(id);
39
+ for (const parent of mod?.importers ?? []) {
40
+ if (parent.id) {
41
+ propagateMetadata.call(this, parent.id, "propagation", "in-tree");
42
+ }
43
+ }
44
+ }
37
45
  if (injectExp.test(source)) {
38
46
  propagateMetadata.call(this, id, "propagation", "in-tree");
39
47
  }
@@ -65,10 +73,21 @@ function astroHeadBuildPlugin(internals) {
65
73
  continue;
66
74
  for (const [id, mod] of Object.entries(output.modules)) {
67
75
  const modinfo = this.getModuleInfo(id);
68
- if (modinfo && getAstroMetadata(modinfo)?.containsHead) {
69
- for (const [pageInfo] of getTopLevelPages(id, this)) {
70
- let metadata = getOrCreateMetadata(pageInfo.id);
71
- metadata.containsHead = true;
76
+ if (modinfo) {
77
+ const meta = getAstroMetadata(modinfo);
78
+ if (meta?.containsHead) {
79
+ for (const [pageInfo] of getTopLevelPages(id, this)) {
80
+ let metadata = getOrCreateMetadata(pageInfo.id);
81
+ metadata.containsHead = true;
82
+ }
83
+ }
84
+ if (meta?.propagation === "self") {
85
+ for (const [info] of walkParentInfos(id, this)) {
86
+ let metadata = getOrCreateMetadata(info.id);
87
+ if (metadata.propagation !== "self") {
88
+ metadata.propagation = "in-tree";
89
+ }
90
+ }
72
91
  }
73
92
  }
74
93
  if (mod.code && injectExp.test(mod.code)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "3.0.10",
3
+ "version": "3.0.12",
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",
@@ -106,7 +106,7 @@
106
106
  "vendor"
107
107
  ],
108
108
  "dependencies": {
109
- "@astrojs/compiler": "^2.0.1",
109
+ "@astrojs/compiler": "^2.1.0",
110
110
  "@babel/core": "^7.22.10",
111
111
  "@babel/generator": "^7.22.10",
112
112
  "@babel/parser": "^7.22.10",
@@ -159,7 +159,7 @@
159
159
  "yargs-parser": "^21.1.1",
160
160
  "zod": "3.21.1",
161
161
  "@astrojs/internal-helpers": "0.2.0",
162
- "@astrojs/markdown-remark": "3.0.0",
162
+ "@astrojs/markdown-remark": "3.1.0",
163
163
  "@astrojs/telemetry": "3.0.1"
164
164
  },
165
165
  "optionalDependencies": {